mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-28 15:54:56 +00:00
feat(form_builder): add contact form with validation and submission handling
- Created contact-form.json defining the structure and validation for the contact form. - Added package.json for form_builder package with dependencies and exports. - Implemented functions.json for form field handlers and validation functions. - Configured storybook for form_builder with various form field stories. - Established style tokens for form fields including colors and spacing. - Defined validation patterns and functions for form fields in validators.json. feat(notification_center): introduce notification components and event handling - Added ui.json for notification components including summary, toast, and list. - Created schema.json for Notification entity with fields and relations. - Implemented event handlers for notification events in handlers.json. - Established package.json for notification_center with components and scripts. - Developed functions.json for notification management and display functions. - Configured storybook for notification_center with various notification stories. - Defined style tokens for notifications including colors and spacing.
This commit is contained in:
433
packages/form_builder/components/ui.json
Normal file
433
packages/form_builder/components/ui.json
Normal file
@@ -0,0 +1,433 @@
|
||||
{
|
||||
"$schema": "https://metabuilder.dev/schemas/json-script-components.schema.json",
|
||||
"schemaVersion": "2.0.0",
|
||||
"package": "form_builder",
|
||||
"description": "Reusable form field components with built-in validation",
|
||||
"components": [
|
||||
{
|
||||
"id": "form_field",
|
||||
"name": "FormField",
|
||||
"description": "Generic form field with label, validation, and error display",
|
||||
"props": [
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "label",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"type": "string",
|
||||
"default": "text",
|
||||
"enum": ["text", "email", "password", "number", "tel", "url", "textarea"]
|
||||
},
|
||||
{
|
||||
"name": "placeholder",
|
||||
"type": "string",
|
||||
"required": false
|
||||
},
|
||||
{
|
||||
"name": "required",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "helperText",
|
||||
"type": "string",
|
||||
"required": false
|
||||
},
|
||||
{
|
||||
"name": "rows",
|
||||
"type": "number",
|
||||
"default": 3
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
],
|
||||
"state": [
|
||||
{
|
||||
"name": "error",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
{
|
||||
"name": "touched",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
],
|
||||
"handlers": {
|
||||
"onChange": "fields.handleChange",
|
||||
"onBlur": "fields.handleBlur",
|
||||
"validate": "validate.validateField"
|
||||
},
|
||||
"render": {
|
||||
"type": "element",
|
||||
"template": {
|
||||
"type": "Box",
|
||||
"className": "form-field",
|
||||
"children": [
|
||||
{
|
||||
"type": "Label",
|
||||
"htmlFor": "{{name}}",
|
||||
"children": [
|
||||
"{{label}}",
|
||||
{
|
||||
"type": "conditional",
|
||||
"condition": "{{required}}",
|
||||
"then": {
|
||||
"type": "span",
|
||||
"className": "text-red-500",
|
||||
"children": " *"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "conditional",
|
||||
"condition": "{{type === 'textarea'}}",
|
||||
"then": {
|
||||
"type": "Textarea",
|
||||
"id": "{{name}}",
|
||||
"name": "{{name}}",
|
||||
"placeholder": "{{placeholder}}",
|
||||
"required": "{{required}}",
|
||||
"rows": "{{rows}}",
|
||||
"value": "{{value}}",
|
||||
"onChange": "onChange",
|
||||
"onBlur": "onBlur"
|
||||
},
|
||||
"else": {
|
||||
"type": "Input",
|
||||
"id": "{{name}}",
|
||||
"name": "{{name}}",
|
||||
"type": "{{type}}",
|
||||
"placeholder": "{{placeholder}}",
|
||||
"required": "{{required}}",
|
||||
"value": "{{value}}",
|
||||
"onChange": "onChange",
|
||||
"onBlur": "onBlur"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "conditional",
|
||||
"condition": "{{helperText && !error}}",
|
||||
"then": {
|
||||
"type": "Text",
|
||||
"variant": "caption",
|
||||
"color": "secondary",
|
||||
"children": "{{helperText}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "conditional",
|
||||
"condition": "{{error && touched}}",
|
||||
"then": {
|
||||
"type": "Text",
|
||||
"variant": "caption",
|
||||
"color": "error",
|
||||
"children": "{{error}}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "email_field",
|
||||
"name": "EmailField",
|
||||
"description": "Email input field with validation",
|
||||
"props": [
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"default": "email"
|
||||
},
|
||||
{
|
||||
"name": "label",
|
||||
"type": "string",
|
||||
"default": "Email"
|
||||
},
|
||||
{
|
||||
"name": "required",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
],
|
||||
"handlers": {
|
||||
"validate": "validate.validateEmail"
|
||||
},
|
||||
"render": {
|
||||
"type": "element",
|
||||
"template": {
|
||||
"type": "FormField",
|
||||
"name": "{{name}}",
|
||||
"label": "{{label}}",
|
||||
"type": "email",
|
||||
"required": "{{required}}",
|
||||
"placeholder": "you@example.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "password_field",
|
||||
"name": "PasswordField",
|
||||
"description": "Password input field with show/hide toggle",
|
||||
"props": [
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"default": "password"
|
||||
},
|
||||
{
|
||||
"name": "label",
|
||||
"type": "string",
|
||||
"default": "Password"
|
||||
},
|
||||
{
|
||||
"name": "required",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"name": "showStrength",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
],
|
||||
"state": [
|
||||
{
|
||||
"name": "showPassword",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
],
|
||||
"handlers": {
|
||||
"toggleVisibility": "fields.togglePasswordVisibility",
|
||||
"validate": "validate.validatePassword"
|
||||
},
|
||||
"render": {
|
||||
"type": "element",
|
||||
"template": {
|
||||
"type": "Box",
|
||||
"className": "password-field",
|
||||
"children": [
|
||||
{
|
||||
"type": "FormField",
|
||||
"name": "{{name}}",
|
||||
"label": "{{label}}",
|
||||
"type": "{{showPassword ? 'text' : 'password'}}",
|
||||
"required": "{{required}}"
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"variant": "ghost",
|
||||
"size": "sm",
|
||||
"onClick": "toggleVisibility",
|
||||
"children": "{{showPassword ? 'Hide' : 'Show'}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "search_bar",
|
||||
"name": "SearchBar",
|
||||
"description": "Search input with icon and clear button",
|
||||
"props": [
|
||||
{
|
||||
"name": "placeholder",
|
||||
"type": "string",
|
||||
"default": "Search..."
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
],
|
||||
"handlers": {
|
||||
"onChange": "fields.handleSearch",
|
||||
"onClear": "fields.clearSearch"
|
||||
},
|
||||
"render": {
|
||||
"type": "element",
|
||||
"template": {
|
||||
"type": "Box",
|
||||
"className": "search-bar",
|
||||
"children": [
|
||||
{
|
||||
"type": "Icon",
|
||||
"name": "Search",
|
||||
"size": 20
|
||||
},
|
||||
{
|
||||
"type": "Input",
|
||||
"type": "search",
|
||||
"placeholder": "{{placeholder}}",
|
||||
"value": "{{value}}",
|
||||
"onChange": "onChange"
|
||||
},
|
||||
{
|
||||
"type": "conditional",
|
||||
"condition": "{{value}}",
|
||||
"then": {
|
||||
"type": "Button",
|
||||
"variant": "ghost",
|
||||
"size": "sm",
|
||||
"onClick": "onClear",
|
||||
"children": [
|
||||
{
|
||||
"type": "Icon",
|
||||
"name": "X",
|
||||
"size": 16
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "contact_form",
|
||||
"name": "ContactForm",
|
||||
"description": "Complete contact form with name, email, and message",
|
||||
"props": [
|
||||
{
|
||||
"name": "title",
|
||||
"type": "string",
|
||||
"default": "Contact form"
|
||||
},
|
||||
{
|
||||
"name": "description",
|
||||
"type": "string",
|
||||
"default": "Collect a name, email, and short message with simple validation."
|
||||
},
|
||||
{
|
||||
"name": "submitLabel",
|
||||
"type": "string",
|
||||
"default": "Send message"
|
||||
}
|
||||
],
|
||||
"state": [
|
||||
{
|
||||
"name": "submitted",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "loading",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
],
|
||||
"handlers": {
|
||||
"onSubmit": "contact_form.handleSubmit",
|
||||
"validate": "contact_form.validate"
|
||||
},
|
||||
"render": {
|
||||
"type": "element",
|
||||
"template": {
|
||||
"type": "Card",
|
||||
"className": "max-w-xl",
|
||||
"children": [
|
||||
{
|
||||
"type": "CardHeader",
|
||||
"children": [
|
||||
{
|
||||
"type": "CardTitle",
|
||||
"text": "{{title}}"
|
||||
},
|
||||
{
|
||||
"type": "CardDescription",
|
||||
"text": "{{description}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "CardContent",
|
||||
"children": [
|
||||
{
|
||||
"type": "conditional",
|
||||
"condition": "{{!submitted}}",
|
||||
"then": {
|
||||
"type": "form",
|
||||
"className": "space-y-4",
|
||||
"onSubmit": "onSubmit",
|
||||
"children": [
|
||||
{
|
||||
"type": "FormField",
|
||||
"name": "name",
|
||||
"label": "Name",
|
||||
"placeholder": "Your name",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "FormField",
|
||||
"name": "email",
|
||||
"label": "Email",
|
||||
"type": "email",
|
||||
"placeholder": "you@example.com",
|
||||
"required": true,
|
||||
"helperText": "We will only use this to reply to your note."
|
||||
},
|
||||
{
|
||||
"type": "FormField",
|
||||
"name": "message",
|
||||
"label": "Message",
|
||||
"type": "textarea",
|
||||
"placeholder": "How can we help?",
|
||||
"required": true,
|
||||
"rows": 4
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"type": "submit",
|
||||
"disabled": "{{loading}}",
|
||||
"children": "{{loading ? 'Sending...' : submitLabel}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"else": {
|
||||
"type": "Box",
|
||||
"className": "text-center py-8",
|
||||
"children": [
|
||||
{
|
||||
"type": "Icon",
|
||||
"name": "CheckCircle",
|
||||
"size": 48,
|
||||
"color": "success"
|
||||
},
|
||||
{
|
||||
"type": "Text",
|
||||
"variant": "h6",
|
||||
"children": "Message sent"
|
||||
},
|
||||
{
|
||||
"type": "Text",
|
||||
"variant": "body2",
|
||||
"color": "secondary",
|
||||
"children": "Thanks for reaching out. We will get back to you shortly."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"exports": {
|
||||
"components": ["FormField", "EmailField", "PasswordField", "NumberField", "SearchBar", "ContactForm"]
|
||||
}
|
||||
}
|
||||
71
packages/form_builder/forms/contact-form.json
Normal file
71
packages/form_builder/forms/contact-form.json
Normal file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"$schema": "https://metabuilder.dev/schemas/forms.schema.json",
|
||||
"schemaVersion": "1.0.0",
|
||||
"package": "form_builder",
|
||||
"description": "Form definitions for form builder package",
|
||||
"forms": [
|
||||
{
|
||||
"id": "contact_form",
|
||||
"name": "ContactForm",
|
||||
"title": "Contact Us",
|
||||
"description": "Send us a message",
|
||||
"layout": "vertical",
|
||||
"fields": [
|
||||
{
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"label": "Name",
|
||||
"placeholder": "Your name",
|
||||
"required": true,
|
||||
"validation": {
|
||||
"required": "Name is required",
|
||||
"minLength": 2,
|
||||
"maxLength": 100,
|
||||
"messages": {
|
||||
"minLength": "Name must be at least 2 characters",
|
||||
"maxLength": "Name cannot exceed 100 characters"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "email",
|
||||
"type": "email",
|
||||
"label": "Email",
|
||||
"placeholder": "you@example.com",
|
||||
"required": true,
|
||||
"helpText": "We will only use this to reply to your note.",
|
||||
"validation": {
|
||||
"required": "Email is required",
|
||||
"email": true,
|
||||
"messages": {
|
||||
"email": "Please enter a valid email address"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "message",
|
||||
"type": "textarea",
|
||||
"label": "Message",
|
||||
"placeholder": "How can we help?",
|
||||
"required": true,
|
||||
"rows": 4,
|
||||
"validation": {
|
||||
"required": "Message is required",
|
||||
"minLength": 10,
|
||||
"maxLength": 1000,
|
||||
"messages": {
|
||||
"minLength": "Message must be at least 10 characters",
|
||||
"maxLength": "Message cannot exceed 1000 characters"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"submitButton": {
|
||||
"label": "Send message",
|
||||
"variant": "primary"
|
||||
},
|
||||
"onSubmit": "contact_form.handleSubmit",
|
||||
"successMessage": "Thanks for reaching out. We will get back to you shortly."
|
||||
}
|
||||
]
|
||||
}
|
||||
53
packages/form_builder/package.json
Normal file
53
packages/form_builder/package.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"$schema": "https://metabuilder.dev/schemas/package-metadata.schema.json",
|
||||
"packageId": "form_builder",
|
||||
"name": "Form Builder",
|
||||
"version": "1.0.0",
|
||||
"description": "Form fields, validation, and submission handling",
|
||||
"author": "MetaBuilder",
|
||||
"license": "MIT",
|
||||
"category": "ui",
|
||||
"minLevel": 1,
|
||||
"primary": false,
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"lua_test": "*"
|
||||
},
|
||||
"exports": {
|
||||
"components": [
|
||||
"FormField",
|
||||
"EmailField",
|
||||
"PasswordField",
|
||||
"NumberField",
|
||||
"SearchBar",
|
||||
"ContactForm"
|
||||
],
|
||||
"scripts": [
|
||||
"fields",
|
||||
"validate",
|
||||
"contact_form"
|
||||
]
|
||||
},
|
||||
"tests": {
|
||||
"scripts": [
|
||||
"tests/metadata.test.lua",
|
||||
"tests/components.test.lua",
|
||||
"tests/validate.test.lua",
|
||||
"tests/contact_form.test.lua"
|
||||
],
|
||||
"parameterized": [
|
||||
{
|
||||
"parameters": "tests/metadata.cases.json"
|
||||
},
|
||||
{
|
||||
"parameters": "tests/components.cases.json"
|
||||
},
|
||||
{
|
||||
"parameters": "tests/validate.cases.json"
|
||||
},
|
||||
{
|
||||
"parameters": "tests/contact_form.cases.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
129
packages/form_builder/scripts/functions.json
Normal file
129
packages/form_builder/scripts/functions.json
Normal file
@@ -0,0 +1,129 @@
|
||||
{
|
||||
"$schema": "https://metabuilder.dev/schemas/json-script.schema.json",
|
||||
"schemaVersion": "2.2.0",
|
||||
"package": "form_builder",
|
||||
"description": "Form field handlers and validation functions",
|
||||
"functions": [
|
||||
{
|
||||
"id": "fields_handle_change",
|
||||
"name": "handleChange",
|
||||
"exported": true,
|
||||
"description": "Handle field value change",
|
||||
"category": "handlers",
|
||||
"luaScript": "fields.lua"
|
||||
},
|
||||
{
|
||||
"id": "fields_handle_blur",
|
||||
"name": "handleBlur",
|
||||
"exported": true,
|
||||
"description": "Handle field blur event",
|
||||
"category": "handlers",
|
||||
"luaScript": "fields.lua"
|
||||
},
|
||||
{
|
||||
"id": "fields_handle_search",
|
||||
"name": "handleSearch",
|
||||
"exported": true,
|
||||
"description": "Handle search input change",
|
||||
"category": "handlers",
|
||||
"luaScript": "fields.lua"
|
||||
},
|
||||
{
|
||||
"id": "fields_clear_search",
|
||||
"name": "clearSearch",
|
||||
"exported": true,
|
||||
"description": "Clear search input",
|
||||
"category": "handlers",
|
||||
"luaScript": "fields.lua"
|
||||
},
|
||||
{
|
||||
"id": "fields_toggle_password",
|
||||
"name": "togglePasswordVisibility",
|
||||
"exported": true,
|
||||
"description": "Toggle password visibility",
|
||||
"category": "handlers",
|
||||
"luaScript": "fields.lua"
|
||||
},
|
||||
{
|
||||
"id": "validate_field",
|
||||
"name": "validateField",
|
||||
"exported": true,
|
||||
"description": "Validate a single form field",
|
||||
"category": "validation",
|
||||
"luaScript": "validate.lua"
|
||||
},
|
||||
{
|
||||
"id": "validate_email",
|
||||
"name": "validateEmail",
|
||||
"exported": true,
|
||||
"description": "Validate email address format",
|
||||
"category": "validation",
|
||||
"luaScript": "validate.lua"
|
||||
},
|
||||
{
|
||||
"id": "validate_password",
|
||||
"name": "validatePassword",
|
||||
"exported": true,
|
||||
"description": "Validate password strength",
|
||||
"category": "validation",
|
||||
"luaScript": "validate.lua"
|
||||
},
|
||||
{
|
||||
"id": "validate_required",
|
||||
"name": "validateRequired",
|
||||
"exported": true,
|
||||
"description": "Check if required field has value",
|
||||
"category": "validation",
|
||||
"luaScript": "validate.lua"
|
||||
},
|
||||
{
|
||||
"id": "validate_form",
|
||||
"name": "validateForm",
|
||||
"exported": true,
|
||||
"description": "Validate entire form",
|
||||
"category": "validation",
|
||||
"luaScript": "validate.lua"
|
||||
},
|
||||
{
|
||||
"id": "contact_form_handle_submit",
|
||||
"name": "handleSubmit",
|
||||
"exported": true,
|
||||
"description": "Handle contact form submission",
|
||||
"category": "forms",
|
||||
"luaScript": "contact_form.lua"
|
||||
},
|
||||
{
|
||||
"id": "contact_form_validate",
|
||||
"name": "validate",
|
||||
"exported": true,
|
||||
"description": "Validate contact form",
|
||||
"category": "forms",
|
||||
"luaScript": "contact_form.lua"
|
||||
},
|
||||
{
|
||||
"id": "contact_form_create_state",
|
||||
"name": "createInitialState",
|
||||
"exported": true,
|
||||
"description": "Create initial form state",
|
||||
"category": "forms",
|
||||
"luaScript": "contact_form.lua"
|
||||
}
|
||||
],
|
||||
"exports": {
|
||||
"functions": [
|
||||
"handleChange",
|
||||
"handleBlur",
|
||||
"handleSearch",
|
||||
"clearSearch",
|
||||
"togglePasswordVisibility",
|
||||
"validateField",
|
||||
"validateEmail",
|
||||
"validatePassword",
|
||||
"validateRequired",
|
||||
"validateForm",
|
||||
"handleSubmit",
|
||||
"validate",
|
||||
"createInitialState"
|
||||
]
|
||||
}
|
||||
}
|
||||
61
packages/form_builder/storybook/config.json
Normal file
61
packages/form_builder/storybook/config.json
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"$schema": "https://metabuilder.dev/schemas/package-storybook.schema.json",
|
||||
"featured": false,
|
||||
"title": "Form Builder",
|
||||
"description": "Reusable form fields with built-in validation",
|
||||
"stories": [
|
||||
{
|
||||
"name": "FormFields",
|
||||
"render": "fields",
|
||||
"description": "Various form field types with validation",
|
||||
"type": "component"
|
||||
},
|
||||
{
|
||||
"name": "ContactForm",
|
||||
"render": "contact_form",
|
||||
"description": "Complete contact form example",
|
||||
"type": "component"
|
||||
},
|
||||
{
|
||||
"name": "EmailField",
|
||||
"render": "fields",
|
||||
"description": "Email input with validation"
|
||||
},
|
||||
{
|
||||
"name": "PasswordField",
|
||||
"render": "fields",
|
||||
"description": "Password field with show/hide toggle"
|
||||
},
|
||||
{
|
||||
"name": "SearchBar",
|
||||
"render": "fields",
|
||||
"description": "Search input with clear button"
|
||||
}
|
||||
],
|
||||
"renders": {
|
||||
"fields": {
|
||||
"description": "Form field components showcase"
|
||||
},
|
||||
"contact_form": {
|
||||
"description": "Contact form with validation",
|
||||
"featured": true
|
||||
}
|
||||
},
|
||||
"defaultContext": {
|
||||
"user": {
|
||||
"id": "demo-user",
|
||||
"username": "demo_user",
|
||||
"level": 1
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"renderFunctions": ["fields", "validate", "contact_form"],
|
||||
"ignoredScripts": ["tests"]
|
||||
},
|
||||
"parameters": {
|
||||
"layout": "padded",
|
||||
"backgrounds": {
|
||||
"default": "light"
|
||||
}
|
||||
}
|
||||
}
|
||||
22
packages/form_builder/styles/tokens.json
Normal file
22
packages/form_builder/styles/tokens.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"$schema": "https://metabuilder.dev/schemas/package-styles.schema.json",
|
||||
"schemaVersion": "2.0.0",
|
||||
"colors": {
|
||||
"fieldBorder": "#d1d5db",
|
||||
"fieldBorderFocus": "#3b82f6",
|
||||
"fieldBorderError": "#ef4444",
|
||||
"fieldBackground": "#ffffff",
|
||||
"fieldText": "#1f2937",
|
||||
"labelText": "#374151",
|
||||
"helperText": "#6b7280",
|
||||
"errorText": "#ef4444"
|
||||
},
|
||||
"spacing": {
|
||||
"fieldPadding": "8px 12px",
|
||||
"labelMargin": "0 0 4px 0",
|
||||
"helperMargin": "4px 0 0 0"
|
||||
},
|
||||
"borderRadius": {
|
||||
"field": "6px"
|
||||
}
|
||||
}
|
||||
123
packages/form_builder/validation/validators.json
Normal file
123
packages/form_builder/validation/validators.json
Normal file
@@ -0,0 +1,123 @@
|
||||
{
|
||||
"$schema": "https://metabuilder.dev/schemas/validation.schema.json",
|
||||
"schemaVersion": "2.0.0",
|
||||
"package": "form_builder",
|
||||
"description": "Validation patterns and functions for form fields",
|
||||
"patterns": {
|
||||
"email": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
||||
"password": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).{8,}$",
|
||||
"url": "^https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)$",
|
||||
"phone": "^[\\+]?[(]?[0-9]{3}[)]?[-\\s\\.]?[0-9]{3}[-\\s\\.]?[0-9]{4,6}$",
|
||||
"zipCode": "^[0-9]{5}(?:-[0-9]{4})?$",
|
||||
"username": "^[a-zA-Z0-9_-]{3,16}$"
|
||||
},
|
||||
"functions": [
|
||||
{
|
||||
"id": "validate_email",
|
||||
"name": "validateEmail",
|
||||
"description": "Validate email address format",
|
||||
"params": [
|
||||
{
|
||||
"name": "email",
|
||||
"type": "string",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"returnType": "boolean",
|
||||
"async": false,
|
||||
"pattern": "email",
|
||||
"errorMessage": "Please enter a valid email address"
|
||||
},
|
||||
{
|
||||
"id": "validate_password",
|
||||
"name": "validatePassword",
|
||||
"description": "Validate password strength (min 8 chars, uppercase, lowercase, number)",
|
||||
"params": [
|
||||
{
|
||||
"name": "password",
|
||||
"type": "string",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"returnType": "boolean",
|
||||
"async": false,
|
||||
"pattern": "password",
|
||||
"errorMessage": "Password must be at least 8 characters and contain uppercase, lowercase, and numbers"
|
||||
},
|
||||
{
|
||||
"id": "validate_required",
|
||||
"name": "validateRequired",
|
||||
"description": "Check if field has a value",
|
||||
"params": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": "any",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"returnType": "boolean",
|
||||
"async": false,
|
||||
"errorMessage": "This field is required"
|
||||
},
|
||||
{
|
||||
"id": "validate_min_length",
|
||||
"name": "validateMinLength",
|
||||
"description": "Check minimum string length",
|
||||
"params": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "minLength",
|
||||
"type": "number",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"returnType": "boolean",
|
||||
"async": false,
|
||||
"errorMessage": "Must be at least ${minLength} characters"
|
||||
},
|
||||
{
|
||||
"id": "validate_max_length",
|
||||
"name": "validateMaxLength",
|
||||
"description": "Check maximum string length",
|
||||
"params": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "maxLength",
|
||||
"type": "number",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"returnType": "boolean",
|
||||
"async": false,
|
||||
"errorMessage": "Must be no more than ${maxLength} characters"
|
||||
},
|
||||
{
|
||||
"id": "validate_url",
|
||||
"name": "validateURL",
|
||||
"description": "Validate URL format",
|
||||
"params": [
|
||||
{
|
||||
"name": "url",
|
||||
"type": "string",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"returnType": "boolean",
|
||||
"async": false,
|
||||
"pattern": "url",
|
||||
"errorMessage": "Please enter a valid URL"
|
||||
}
|
||||
],
|
||||
"exports": {
|
||||
"patterns": ["email", "password", "url", "phone", "zipCode", "username"],
|
||||
"functions": ["validateEmail", "validatePassword", "validateRequired", "validateMinLength", "validateMaxLength", "validateURL"]
|
||||
}
|
||||
}
|
||||
281
packages/notification_center/components/ui.json
Normal file
281
packages/notification_center/components/ui.json
Normal file
@@ -0,0 +1,281 @@
|
||||
{
|
||||
"$schema": "https://metabuilder.dev/schemas/json-script-components.schema.json",
|
||||
"schemaVersion": "2.0.0",
|
||||
"package": "notification_center",
|
||||
"description": "Notification components including toast, list, and summary",
|
||||
"components": [
|
||||
{
|
||||
"id": "notification_summary",
|
||||
"name": "NotificationSummary",
|
||||
"description": "Summary card showing notification counts by severity level",
|
||||
"props": [
|
||||
{
|
||||
"name": "title",
|
||||
"type": "string",
|
||||
"default": "Notification Summary"
|
||||
},
|
||||
{
|
||||
"name": "subtitle",
|
||||
"type": "string",
|
||||
"required": false
|
||||
},
|
||||
{
|
||||
"name": "totalLabel",
|
||||
"type": "string",
|
||||
"default": "Total"
|
||||
}
|
||||
],
|
||||
"state": [
|
||||
{
|
||||
"name": "total",
|
||||
"type": "number",
|
||||
"default": 0
|
||||
},
|
||||
{
|
||||
"name": "items",
|
||||
"type": "array",
|
||||
"default": []
|
||||
}
|
||||
],
|
||||
"handlers": {
|
||||
"init": "summary.prepareSummary"
|
||||
},
|
||||
"render": {
|
||||
"type": "element",
|
||||
"template": {
|
||||
"type": "Card",
|
||||
"className": "space-y-4 p-4",
|
||||
"children": [
|
||||
{
|
||||
"type": "Box",
|
||||
"className": "space-y-1",
|
||||
"children": [
|
||||
{
|
||||
"type": "Typography",
|
||||
"variant": "overline",
|
||||
"className": "tracking-[0.3em] text-muted-foreground",
|
||||
"children": "{{title}}"
|
||||
},
|
||||
{
|
||||
"type": "Box",
|
||||
"className": "flex items-baseline justify-between gap-3",
|
||||
"children": [
|
||||
{
|
||||
"type": "Typography",
|
||||
"variant": "h3",
|
||||
"className": "font-bold",
|
||||
"children": "{{total}}"
|
||||
},
|
||||
{
|
||||
"type": "Badge",
|
||||
"variant": "secondary",
|
||||
"label": "{{totalLabel}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Separator"
|
||||
},
|
||||
{
|
||||
"type": "List",
|
||||
"dataSource": "items",
|
||||
"className": "space-y-3",
|
||||
"itemTemplate": {
|
||||
"type": "Box",
|
||||
"className": "flex items-center justify-between gap-3",
|
||||
"children": [
|
||||
{
|
||||
"type": "Box",
|
||||
"children": [
|
||||
{
|
||||
"type": "Typography",
|
||||
"variant": "body2",
|
||||
"fontWeight": "semibold",
|
||||
"children": "{{item.label}}"
|
||||
},
|
||||
{
|
||||
"type": "Typography",
|
||||
"variant": "caption",
|
||||
"color": "textSecondary",
|
||||
"children": "{{item.hint}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Box",
|
||||
"className": "flex items-center gap-2",
|
||||
"children": [
|
||||
{
|
||||
"type": "Badge",
|
||||
"variant": "outline",
|
||||
"className": "{{item.classes}}",
|
||||
"label": "{{item.count}}"
|
||||
},
|
||||
{
|
||||
"type": "Typography",
|
||||
"variant": "overline",
|
||||
"className": "tracking-[0.4em]",
|
||||
"children": "{{item.severity}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "notification_toast",
|
||||
"name": "NotificationToast",
|
||||
"description": "Toast notification popup",
|
||||
"props": [
|
||||
{
|
||||
"name": "type",
|
||||
"type": "string",
|
||||
"default": "info",
|
||||
"enum": ["info", "success", "warning", "error"]
|
||||
},
|
||||
{
|
||||
"name": "title",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "message",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "duration",
|
||||
"type": "number",
|
||||
"default": 5000
|
||||
}
|
||||
],
|
||||
"handlers": {
|
||||
"onDismiss": "toast.dismiss"
|
||||
},
|
||||
"render": {
|
||||
"type": "element",
|
||||
"template": {
|
||||
"type": "Box",
|
||||
"className": "toast toast-{{type}}",
|
||||
"children": [
|
||||
{
|
||||
"type": "Icon",
|
||||
"name": "{{type === 'success' ? 'CheckCircle' : type === 'error' ? 'XCircle' : type === 'warning' ? 'AlertTriangle' : 'Info'}}",
|
||||
"size": 20
|
||||
},
|
||||
{
|
||||
"type": "Box",
|
||||
"children": [
|
||||
{
|
||||
"type": "Text",
|
||||
"fontWeight": "semibold",
|
||||
"children": "{{title}}"
|
||||
},
|
||||
{
|
||||
"type": "Text",
|
||||
"variant": "caption",
|
||||
"children": "{{message}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"variant": "ghost",
|
||||
"size": "sm",
|
||||
"onClick": "onDismiss",
|
||||
"children": [
|
||||
{
|
||||
"type": "Icon",
|
||||
"name": "X",
|
||||
"size": 16
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "notification_list",
|
||||
"name": "NotificationList",
|
||||
"description": "List of notifications with read/unread status",
|
||||
"props": [
|
||||
{
|
||||
"name": "notifications",
|
||||
"type": "array",
|
||||
"default": []
|
||||
},
|
||||
{
|
||||
"name": "showUnreadOnly",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
],
|
||||
"handlers": {
|
||||
"markAsRead": "list.markAsRead",
|
||||
"dismiss": "list.dismiss"
|
||||
},
|
||||
"render": {
|
||||
"type": "element",
|
||||
"template": {
|
||||
"type": "List",
|
||||
"dataSource": "notifications",
|
||||
"className": "notification-list",
|
||||
"itemTemplate": {
|
||||
"type": "Box",
|
||||
"className": "notification-item {{item.read ? 'read' : 'unread'}}",
|
||||
"children": [
|
||||
{
|
||||
"type": "Icon",
|
||||
"name": "{{item.icon || 'Bell'}}",
|
||||
"size": 24,
|
||||
"color": "{{item.type}}"
|
||||
},
|
||||
{
|
||||
"type": "Box",
|
||||
"className": "flex-1",
|
||||
"children": [
|
||||
{
|
||||
"type": "Text",
|
||||
"fontWeight": "{{item.read ? 'normal' : 'semibold'}}",
|
||||
"children": "{{item.title}}"
|
||||
},
|
||||
{
|
||||
"type": "Text",
|
||||
"variant": "caption",
|
||||
"color": "secondary",
|
||||
"children": "{{item.message}}"
|
||||
},
|
||||
{
|
||||
"type": "Text",
|
||||
"variant": "caption",
|
||||
"color": "secondary",
|
||||
"children": "{{item.createdAt}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "conditional",
|
||||
"condition": "{{!item.read}}",
|
||||
"then": {
|
||||
"type": "Badge",
|
||||
"variant": "dot",
|
||||
"color": "primary"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"exports": {
|
||||
"components": ["NotificationSummary", "NotificationToast", "NotificationList"]
|
||||
}
|
||||
}
|
||||
115
packages/notification_center/entities/schema.json
Normal file
115
packages/notification_center/entities/schema.json
Normal file
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"$schema": "https://metabuilder.dev/schemas/entities.schema.json",
|
||||
"schemaVersion": "2.0.0",
|
||||
"entities": [
|
||||
{
|
||||
"name": "Notification",
|
||||
"version": "1.0",
|
||||
"description": "User notification for alerts, messages, and system events",
|
||||
"primaryKey": "id",
|
||||
"timestamps": false,
|
||||
"softDelete": false,
|
||||
"fields": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"generated": true,
|
||||
"description": "Unique identifier (CUID)"
|
||||
},
|
||||
"tenantId": {
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"index": true,
|
||||
"description": "Tenant identifier"
|
||||
},
|
||||
"userId": {
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"index": true,
|
||||
"description": "User who receives this notification"
|
||||
},
|
||||
"type": {
|
||||
"type": "enum",
|
||||
"required": true,
|
||||
"enum": ["info", "warning", "success", "error", "mention", "reply", "follow", "like", "system"],
|
||||
"description": "Notification type/severity"
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"maxLength": 200,
|
||||
"description": "Notification title"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"description": "Notification message body"
|
||||
},
|
||||
"icon": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Icon name for display"
|
||||
},
|
||||
"read": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"index": true,
|
||||
"description": "Whether notification has been read"
|
||||
},
|
||||
"data": {
|
||||
"type": "text",
|
||||
"nullable": true,
|
||||
"description": "JSON: action URLs, entity references, etc."
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "bigint",
|
||||
"required": true,
|
||||
"index": true,
|
||||
"description": "Creation timestamp in milliseconds"
|
||||
},
|
||||
"expiresAt": {
|
||||
"type": "bigint",
|
||||
"nullable": true,
|
||||
"index": true,
|
||||
"description": "Expiration timestamp in milliseconds"
|
||||
}
|
||||
},
|
||||
"indexes": [
|
||||
{
|
||||
"fields": ["tenantId"],
|
||||
"name": "idx_notification_tenant"
|
||||
},
|
||||
{
|
||||
"fields": ["userId", "read"],
|
||||
"name": "idx_notification_user_read"
|
||||
},
|
||||
{
|
||||
"fields": ["createdAt"],
|
||||
"name": "idx_notification_created"
|
||||
}
|
||||
],
|
||||
"relations": [
|
||||
{
|
||||
"name": "tenant",
|
||||
"type": "belongsTo",
|
||||
"entity": "Tenant",
|
||||
"field": "tenantId",
|
||||
"onDelete": "Cascade"
|
||||
},
|
||||
{
|
||||
"name": "user",
|
||||
"type": "belongsTo",
|
||||
"entity": "User",
|
||||
"field": "userId",
|
||||
"onDelete": "Cascade"
|
||||
}
|
||||
],
|
||||
"acl": {
|
||||
"create": ["system", "admin"],
|
||||
"read": ["self"],
|
||||
"update": ["self"],
|
||||
"delete": ["self"],
|
||||
"rowLevel": "userId = currentUser.id"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
48
packages/notification_center/events/handlers.json
Normal file
48
packages/notification_center/events/handlers.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"$schema": "https://metabuilder.dev/schemas/events.schema.json",
|
||||
"schemaVersion": "1.0.0",
|
||||
"package": "notification_center",
|
||||
"description": "Notification event definitions and handlers",
|
||||
"events": [
|
||||
{
|
||||
"name": "notification.created",
|
||||
"version": "1.0.0",
|
||||
"description": "Fired when a new notification is created",
|
||||
"payload": "Notification"
|
||||
},
|
||||
{
|
||||
"name": "notification.read",
|
||||
"version": "1.0.0",
|
||||
"description": "Fired when a notification is marked as read",
|
||||
"payload": {
|
||||
"notificationId": "string",
|
||||
"userId": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "notification.dismissed",
|
||||
"version": "1.0.0",
|
||||
"description": "Fired when a notification is dismissed",
|
||||
"payload": {
|
||||
"notificationId": "string",
|
||||
"userId": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"subscribers": [
|
||||
{
|
||||
"id": "show_toast_on_create",
|
||||
"name": "Show Toast on Notification",
|
||||
"events": ["notification.created"],
|
||||
"handler": "toast.showToast",
|
||||
"description": "Display toast when new notification arrives"
|
||||
},
|
||||
{
|
||||
"id": "update_count_on_read",
|
||||
"name": "Update Count on Read",
|
||||
"events": ["notification.read"],
|
||||
"handler": "summary.prepareSummary",
|
||||
"description": "Update notification count when marked as read"
|
||||
}
|
||||
]
|
||||
}
|
||||
43
packages/notification_center/package.json
Normal file
43
packages/notification_center/package.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"$schema": "https://metabuilder.dev/schemas/package-metadata.schema.json",
|
||||
"packageId": "notification_center",
|
||||
"name": "Notification Center",
|
||||
"version": "1.0.0",
|
||||
"description": "Notification center components and summary cards",
|
||||
"author": "MetaBuilder",
|
||||
"license": "MIT",
|
||||
"category": "ui",
|
||||
"minLevel": 1,
|
||||
"primary": false,
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"lua_test": "*"
|
||||
},
|
||||
"exports": {
|
||||
"components": [
|
||||
"NotificationSummary",
|
||||
"NotificationList",
|
||||
"NotificationToast"
|
||||
],
|
||||
"scripts": [
|
||||
"init",
|
||||
"toast",
|
||||
"list",
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
"tests": {
|
||||
"scripts": [
|
||||
"tests/metadata.test.lua",
|
||||
"tests/components.test.lua"
|
||||
],
|
||||
"parameterized": [
|
||||
{
|
||||
"parameters": "tests/metadata.cases.json"
|
||||
},
|
||||
{
|
||||
"parameters": "tests/components.cases.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
83
packages/notification_center/scripts/functions.json
Normal file
83
packages/notification_center/scripts/functions.json
Normal file
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"$schema": "https://metabuilder.dev/schemas/json-script.schema.json",
|
||||
"schemaVersion": "2.2.0",
|
||||
"package": "notification_center",
|
||||
"description": "Notification management and display functions",
|
||||
"functions": [
|
||||
{
|
||||
"id": "init_load",
|
||||
"name": "loadNotifications",
|
||||
"exported": true,
|
||||
"description": "Load user notifications",
|
||||
"category": "lifecycle",
|
||||
"luaScript": "init.lua"
|
||||
},
|
||||
{
|
||||
"id": "toast_show",
|
||||
"name": "showToast",
|
||||
"exported": true,
|
||||
"description": "Display toast notification",
|
||||
"category": "ui",
|
||||
"luaScript": "toast.lua"
|
||||
},
|
||||
{
|
||||
"id": "toast_dismiss",
|
||||
"name": "dismiss",
|
||||
"exported": true,
|
||||
"description": "Dismiss toast notification",
|
||||
"category": "ui",
|
||||
"luaScript": "toast.lua"
|
||||
},
|
||||
{
|
||||
"id": "list_mark_read",
|
||||
"name": "markAsRead",
|
||||
"exported": true,
|
||||
"description": "Mark notification as read",
|
||||
"category": "actions",
|
||||
"luaScript": "list.lua"
|
||||
},
|
||||
{
|
||||
"id": "list_dismiss",
|
||||
"name": "dismiss",
|
||||
"exported": true,
|
||||
"description": "Dismiss notification",
|
||||
"category": "actions",
|
||||
"luaScript": "list.lua"
|
||||
},
|
||||
{
|
||||
"id": "list_mark_all_read",
|
||||
"name": "markAllAsRead",
|
||||
"exported": true,
|
||||
"description": "Mark all notifications as read",
|
||||
"category": "actions",
|
||||
"luaScript": "list.lua"
|
||||
},
|
||||
{
|
||||
"id": "summary_prepare",
|
||||
"name": "prepareSummary",
|
||||
"exported": true,
|
||||
"description": "Prepare notification summary data",
|
||||
"category": "analytics",
|
||||
"luaScript": "summary.lua"
|
||||
},
|
||||
{
|
||||
"id": "summary_count_by_type",
|
||||
"name": "countByType",
|
||||
"exported": true,
|
||||
"description": "Count notifications by type",
|
||||
"category": "analytics",
|
||||
"luaScript": "summary.lua"
|
||||
}
|
||||
],
|
||||
"exports": {
|
||||
"functions": [
|
||||
"loadNotifications",
|
||||
"showToast",
|
||||
"dismiss",
|
||||
"markAsRead",
|
||||
"markAllAsRead",
|
||||
"prepareSummary",
|
||||
"countByType"
|
||||
]
|
||||
}
|
||||
}
|
||||
57
packages/notification_center/storybook/config.json
Normal file
57
packages/notification_center/storybook/config.json
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"$schema": "https://metabuilder.dev/schemas/package-storybook.schema.json",
|
||||
"featured": false,
|
||||
"title": "Notification Center",
|
||||
"description": "Notification management and display components",
|
||||
"stories": [
|
||||
{
|
||||
"name": "NotificationCenter",
|
||||
"render": "init",
|
||||
"description": "Complete notification center with list and summary"
|
||||
},
|
||||
{
|
||||
"name": "NotificationToast",
|
||||
"render": "toast",
|
||||
"description": "Toast notification popup",
|
||||
"args": {
|
||||
"type": "success",
|
||||
"title": "Success",
|
||||
"message": "Your changes have been saved"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "NotificationSummary",
|
||||
"render": "summary",
|
||||
"description": "Notification summary card"
|
||||
}
|
||||
],
|
||||
"renders": {
|
||||
"init": {
|
||||
"description": "Full notification center",
|
||||
"featured": true
|
||||
},
|
||||
"toast": {
|
||||
"description": "Toast notifications"
|
||||
},
|
||||
"summary": {
|
||||
"description": "Notification summary statistics"
|
||||
},
|
||||
"list": {
|
||||
"description": "Notification list view"
|
||||
}
|
||||
},
|
||||
"defaultContext": {
|
||||
"user": {
|
||||
"id": "demo-user",
|
||||
"username": "demo_user",
|
||||
"level": 1
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"renderFunctions": ["init", "toast", "list", "summary"],
|
||||
"ignoredScripts": ["tests"]
|
||||
},
|
||||
"parameters": {
|
||||
"layout": "padded"
|
||||
}
|
||||
}
|
||||
19
packages/notification_center/styles/tokens.json
Normal file
19
packages/notification_center/styles/tokens.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "https://metabuilder.dev/schemas/package-styles.schema.json",
|
||||
"schemaVersion": "2.0.0",
|
||||
"colors": {
|
||||
"notificationInfo": "#3b82f6",
|
||||
"notificationSuccess": "#10b981",
|
||||
"notificationWarning": "#f59e0b",
|
||||
"notificationError": "#ef4444",
|
||||
"notificationUnread": "#6366f1",
|
||||
"notificationRead": "#9ca3af"
|
||||
},
|
||||
"spacing": {
|
||||
"toastPadding": "12px 16px",
|
||||
"notificationItem": "12px"
|
||||
},
|
||||
"shadows": {
|
||||
"toast": "0 4px 12px rgba(0, 0, 0, 0.15)"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user