UNPKG

@stacksjs/stx

Version:

A performant UI Framework. Powered by Bun.

411 lines (394 loc) 12.6 kB
/** * Parse @craft-* component directives from stx template */ export declare function processCraftComponents(content: string, config?: CraftComponentConfig): string; /** * Register a custom Craft component */ export declare function registerCraftComponent(name: string, definition: CraftComponentDefinition): void; /** * Get all registered Craft components */ export declare function getCraftComponents(): Record<string, CraftComponentDefinition>; /** * Built-in Craft component definitions */ export declare const CRAFT_COMPONENTS: { // Input Components button: { nativeType: 'craft-button'; fallbackTag: 'button'; fallbackClasses: 'craft-button'; nativeProps: readonly ['variant', 'size', 'disabled', 'loading'] }; 'text-input': { nativeType: 'craft-text-input'; fallbackTag: 'input'; fallbackClasses: 'craft-text-input'; nativeProps: readonly ['placeholder', 'value', 'type', 'disabled', 'readonly'] }; textarea: { nativeType: 'craft-textarea'; fallbackTag: 'textarea'; fallbackClasses: 'craft-textarea'; nativeProps: readonly ['placeholder', 'value', 'rows', 'disabled', 'readonly'] }; checkbox: { nativeType: 'craft-checkbox'; fallbackTag: 'input'; fallbackClasses: 'craft-checkbox'; nativeProps: readonly ['checked', 'disabled', 'label']; render: (props, children) => unknown }; radio: { nativeType: 'craft-radio'; fallbackTag: 'input'; fallbackClasses: 'craft-radio'; nativeProps: readonly ['checked', 'disabled', 'name', 'value', 'label'] }; select: { nativeType: 'craft-select'; fallbackTag: 'select'; fallbackClasses: 'craft-select'; nativeProps: readonly ['value', 'disabled', 'options', 'placeholder'] }; slider: { nativeType: 'craft-slider'; fallbackTag: 'input'; fallbackClasses: 'craft-slider'; nativeProps: readonly ['value', 'min', 'max', 'step', 'disabled']; render: (props, _children) => unknown }; // Display Components label: { nativeType: 'craft-label'; fallbackTag: 'span'; fallbackClasses: 'craft-label'; nativeProps: readonly ['text', 'for'] }; badge: { nativeType: 'craft-badge'; fallbackTag: 'span'; fallbackClasses: 'craft-badge'; nativeProps: readonly ['variant', 'size'] }; avatar: { nativeType: 'craft-avatar'; fallbackTag: 'div'; fallbackClasses: 'craft-avatar'; nativeProps: readonly ['src', 'alt', 'size', 'fallback']; render: (props, _children) => unknown }; progress: { nativeType: 'craft-progress'; fallbackTag: 'div'; fallbackClasses: 'craft-progress'; nativeProps: readonly ['value', 'max', 'variant']; render: (props, _children) => unknown }; spinner: { nativeType: 'craft-spinner'; fallbackTag: 'div'; fallbackClasses: 'craft-spinner'; nativeProps: readonly ['size']; render: (props, _children) => unknown }; // Layout Components card: { nativeType: 'craft-card'; fallbackTag: 'div'; fallbackClasses: 'craft-card'; nativeProps: readonly ['title', 'subtitle', 'variant'] }; modal: { nativeType: 'craft-modal'; fallbackTag: 'dialog'; fallbackClasses: 'craft-modal'; nativeProps: readonly ['open', 'title', 'closable', 'size']; render: (props, children) => unknown }; tabs: { nativeType: 'craft-tabs'; fallbackTag: 'div'; fallbackClasses: 'craft-tabs'; nativeProps: readonly ['activeTab', 'tabs'] }; accordion: { nativeType: 'craft-accordion'; fallbackTag: 'details'; fallbackClasses: 'craft-accordion'; nativeProps: readonly ['open', 'title']; render: (props, children) => unknown }; divider: { nativeType: 'craft-divider'; fallbackTag: 'hr'; fallbackClasses: 'craft-divider'; nativeProps: readonly ['orientation', 'variant'] }; // Data Components table: { nativeType: 'craft-table'; fallbackTag: 'table'; fallbackClasses: 'craft-table'; nativeProps: readonly ['columns', 'rows', 'sortable', 'selectable'] }; list: { nativeType: 'craft-list'; fallbackTag: 'ul'; fallbackClasses: 'craft-list'; nativeProps: readonly ['items', 'selectable'] }; tree: { nativeType: 'craft-tree'; fallbackTag: 'div'; fallbackClasses: 'craft-tree'; nativeProps: readonly ['nodes', 'expandable', 'selectable'] }; // Feedback Components alert: { nativeType: 'craft-alert'; fallbackTag: 'div'; fallbackClasses: 'craft-alert'; nativeProps: readonly ['variant', 'title', 'dismissible']; render: (props, children) => unknown }; toast: { nativeType: 'craft-toast'; fallbackTag: 'div'; fallbackClasses: 'craft-toast'; nativeProps: readonly ['variant', 'duration', 'position'] }; tooltip: { nativeType: 'craft-tooltip'; fallbackTag: 'span'; fallbackClasses: 'craft-tooltip'; nativeProps: readonly ['content', 'position']; render: (props, children) => unknown }; // Navigation Components menu: { nativeType: 'craft-menu'; fallbackTag: 'nav'; fallbackClasses: 'craft-menu'; nativeProps: readonly ['items', 'orientation'] }; breadcrumb: { nativeType: 'craft-breadcrumb'; fallbackTag: 'nav'; fallbackClasses: 'craft-breadcrumb'; nativeProps: readonly ['items', 'separator'] }; pagination: { nativeType: 'craft-pagination'; fallbackTag: 'nav'; fallbackClasses: 'craft-pagination'; nativeProps: readonly ['total', 'page', 'pageSize'] }; // Advanced Components 'code-editor': { nativeType: 'craft-code-editor'; fallbackTag: 'textarea'; fallbackClasses: 'craft-code-editor'; nativeProps: readonly ['value', 'language', 'theme', 'readonly', 'lineNumbers'] }; 'file-browser': { nativeType: 'craft-file-browser'; fallbackTag: 'div'; fallbackClasses: 'craft-file-browser'; nativeProps: readonly ['path', 'showHidden', 'selectable'] }; 'color-picker': { nativeType: 'craft-color-picker'; fallbackTag: 'input'; fallbackClasses: 'craft-color-picker'; nativeProps: readonly ['value', 'format']; render: (props, _children) => unknown }; 'date-picker': { nativeType: 'craft-date-picker'; fallbackTag: 'input'; fallbackClasses: 'craft-date-picker'; nativeProps: readonly ['value', 'min', 'max', 'format']; render: (props, _children) => unknown }; 'time-picker': { nativeType: 'craft-time-picker'; fallbackTag: 'input'; fallbackClasses: 'craft-time-picker'; nativeProps: readonly ['value', 'min', 'max', 'step']; render: (props, _children) => unknown } }; /** * CSS styles for Craft component fallbacks */ export declare const CRAFT_COMPONENT_STYLES: ` <style id="craft-component-styles"> /* Craft Component Base Styles */ .craft-button { display: inline-flex; align-items: center; justify-content: center; padding: 8px 16px; border: none; border-radius: 6px; font-family: inherit; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s ease; background: var(--craft-primary, #3b82f6); color: white; } .craft-button:hover { opacity: 0.9; } .craft-button:disabled { opacity: 0.5; cursor: not-allowed; } .craft-button-secondary { background: var(--craft-secondary, #6b7280); } .craft-button-outline { background: transparent; border: 1px solid currentColor; color: var(--craft-primary, #3b82f6); } .craft-text-input, .craft-textarea, .craft-select { padding: 8px 12px; border: 1px solid var(--craft-border, #d1d5db); border-radius: 6px; font-family: inherit; font-size: 14px; background: var(--craft-bg, #fff); color: var(--craft-text, #1f2937); transition: border-color 0.2s ease; } .craft-text-input:focus, .craft-textarea:focus, .craft-select:focus { outline: none; border-color: var(--craft-primary, #3b82f6); box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); } .craft-checkbox-wrapper { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; } .craft-checkbox { width: 18px; height: 18px; cursor: pointer; } .craft-slider { width: 100%; height: 6px; border-radius: 3px; cursor: pointer; } .craft-badge { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 9999px; font-size: 12px; font-weight: 500; background: var(--craft-primary, #3b82f6); color: white; } .craft-avatar { display: inline-flex; align-items: center; justify-content: center; background: var(--craft-secondary, #6b7280); color: white; font-weight: 600; overflow: hidden; } .craft-avatar img { width: 100%; height: 100%; object-fit: cover; } .craft-progress { width: 100%; height: 8px; background: var(--craft-border, #e5e7eb); border-radius: 4px; overflow: hidden; } .craft-progress-bar { height: 100%; background: var(--craft-primary, #3b82f6); transition: width 0.3s ease; } .craft-spinner { border: 2px solid var(--craft-border, #e5e7eb); border-top-color: var(--craft-primary, #3b82f6); border-radius: 50%; animation: craft-spin 0.8s linear infinite; } @keyframes craft-spin { to { transform: rotate(360deg); } } .craft-card { background: var(--craft-bg, #fff); border: 1px solid var(--craft-border, #e5e7eb); border-radius: 8px; padding: 16px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } .craft-modal { border: none; border-radius: 12px; padding: 0; max-width: 90vw; max-height: 90vh; box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25); } .craft-modal::backdrop { background: rgba(0,0,0,0.5); } .craft-modal-header { padding: 16px 20px; border-bottom: 1px solid var(--craft-border, #e5e7eb); } .craft-modal-header h2 { margin: 0; font-size: 18px; } .craft-modal-body { padding: 20px; } .craft-accordion { border: 1px solid var(--craft-border, #e5e7eb); border-radius: 6px; overflow: hidden; } .craft-accordion-header { padding: 12px 16px; cursor: pointer; font-weight: 500; background: var(--craft-bg-secondary, #f9fafb); } .craft-accordion-content { padding: 16px; } .craft-divider { border: none; border-top: 1px solid var(--craft-border, #e5e7eb); margin: 16px 0; } .craft-alert { padding: 12px 16px; border-radius: 6px; border-left: 4px solid; } .craft-alert-info { background: #eff6ff; border-color: #3b82f6; color: #1e40af; } .craft-alert-success { background: #f0fdf4; border-color: #22c55e; color: #166534; } .craft-alert-warning { background: #fffbeb; border-color: #f59e0b; color: #92400e; } .craft-alert-error { background: #fef2f2; border-color: #ef4444; color: #991b1b; } .craft-alert-title { font-weight: 600; margin-bottom: 4px; } .craft-tooltip { position: relative; cursor: help; } .craft-tooltip::after { content: attr(data-tooltip); position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); padding: 4px 8px; background: #1f2937; color: white; font-size: 12px; border-radius: 4px; white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity 0.2s; } .craft-tooltip:hover::after { opacity: 1; } .craft-table { width: 100%; border-collapse: collapse; } .craft-table th, .craft-table td { padding: 12px; text-align: left; border-bottom: 1px solid var(--craft-border, #e5e7eb); } .craft-table th { font-weight: 600; background: var(--craft-bg-secondary, #f9fafb); } .craft-list { list-style: none; padding: 0; margin: 0; } .craft-list li { padding: 12px; border-bottom: 1px solid var(--craft-border, #e5e7eb); } .craft-list li:last-child { border-bottom: none; } .craft-code-editor { font-family: 'SF Mono', 'Fira Code', monospace; font-size: 13px; line-height: 1.5; padding: 12px; background: #1e1e1e; color: #d4d4d4; border-radius: 6px; resize: vertical; } /* Dark mode support */ @media (prefers-color-scheme: dark) { .craft-text-input, .craft-textarea, .craft-select, .craft-card { background: #1f2937; color: #f3f4f6; border-color: #374151; } .craft-modal { background: #1f2937; color: #f3f4f6; } .craft-accordion-header { background: #374151; } .craft-table th { background: #374151; } } </style> `; /** * Craft Native Components for stx * * This module provides @craft-* directives that render native components * when running in a Craft environment, with HTML fallbacks for web browsers. * * @example * ```html * <@craft-button variant="primary" @click="handleClick"> * Click Me * </@craft-button> * * <@craft-text-input placeholder="Enter name" :value="name" @change="updateName" /> * * <@craft-modal title="Settings" :open="showSettings"> * Modal content here * </@craft-modal> * ``` */ export declare interface CraftComponentConfig { preferNative?: boolean classPrefix?: string components?: Record<string, CraftComponentDefinition> } export declare interface CraftComponentDefinition { nativeType: string fallbackTag: string fallbackClasses?: string nativeProps?: string[] render?: (props: Record<string, unknown>, children: string) => string } export default craftComponents;