@object-ui/core 3.3.0 → 3.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +20 -1
  3. package/dist/actions/ActionRunner.d.ts +9 -0
  4. package/dist/actions/ActionRunner.js +41 -4
  5. package/dist/adapters/ValueDataSource.js +3 -1
  6. package/dist/registry/Registry.d.ts +47 -0
  7. package/dist/registry/Registry.js +92 -0
  8. package/dist/utils/filter-converter.js +25 -5
  9. package/package.json +32 -8
  10. package/.turbo/turbo-build.log +0 -4
  11. package/src/__benchmarks__/core.bench.ts +0 -64
  12. package/src/__tests__/protocols/DndProtocol.test.ts +0 -186
  13. package/src/__tests__/protocols/KeyboardProtocol.test.ts +0 -177
  14. package/src/__tests__/protocols/NotificationProtocol.test.ts +0 -142
  15. package/src/__tests__/protocols/ResponsiveProtocol.test.ts +0 -176
  16. package/src/__tests__/protocols/SharingProtocol.test.ts +0 -188
  17. package/src/actions/ActionEngine.ts +0 -268
  18. package/src/actions/ActionRunner.ts +0 -717
  19. package/src/actions/TransactionManager.ts +0 -521
  20. package/src/actions/UndoManager.ts +0 -215
  21. package/src/actions/__tests__/ActionEngine.test.ts +0 -206
  22. package/src/actions/__tests__/ActionRunner.params.test.ts +0 -134
  23. package/src/actions/__tests__/ActionRunner.test.ts +0 -711
  24. package/src/actions/__tests__/TransactionManager.test.ts +0 -447
  25. package/src/actions/__tests__/UndoManager.test.ts +0 -320
  26. package/src/actions/index.ts +0 -12
  27. package/src/adapters/ApiDataSource.ts +0 -376
  28. package/src/adapters/README.md +0 -180
  29. package/src/adapters/ValueDataSource.ts +0 -459
  30. package/src/adapters/__tests__/ApiDataSource.test.ts +0 -418
  31. package/src/adapters/__tests__/ValueDataSource.test.ts +0 -571
  32. package/src/adapters/__tests__/resolveDataSource.test.ts +0 -144
  33. package/src/adapters/index.ts +0 -15
  34. package/src/adapters/resolveDataSource.ts +0 -79
  35. package/src/builder/__tests__/schema-builder.test.ts +0 -235
  36. package/src/builder/schema-builder.ts +0 -584
  37. package/src/data-scope/DataScopeManager.ts +0 -269
  38. package/src/data-scope/ViewDataProvider.ts +0 -282
  39. package/src/data-scope/__tests__/DataScopeManager.test.ts +0 -211
  40. package/src/data-scope/__tests__/ViewDataProvider.test.ts +0 -270
  41. package/src/data-scope/index.ts +0 -24
  42. package/src/errors/__tests__/errors.test.ts +0 -292
  43. package/src/errors/index.ts +0 -269
  44. package/src/evaluator/ExpressionCache.ts +0 -206
  45. package/src/evaluator/ExpressionContext.ts +0 -118
  46. package/src/evaluator/ExpressionEvaluator.ts +0 -315
  47. package/src/evaluator/FormulaFunctions.ts +0 -398
  48. package/src/evaluator/SafeExpressionParser.ts +0 -893
  49. package/src/evaluator/__tests__/ExpressionCache.test.ts +0 -135
  50. package/src/evaluator/__tests__/ExpressionContext.test.ts +0 -110
  51. package/src/evaluator/__tests__/ExpressionEvaluator.test.ts +0 -558
  52. package/src/evaluator/__tests__/FormulaFunctions.test.ts +0 -447
  53. package/src/evaluator/index.ts +0 -13
  54. package/src/index.ts +0 -38
  55. package/src/protocols/DndProtocol.ts +0 -168
  56. package/src/protocols/KeyboardProtocol.ts +0 -181
  57. package/src/protocols/NotificationProtocol.ts +0 -150
  58. package/src/protocols/ResponsiveProtocol.ts +0 -210
  59. package/src/protocols/SharingProtocol.ts +0 -185
  60. package/src/protocols/index.ts +0 -13
  61. package/src/query/__tests__/query-ast.test.ts +0 -211
  62. package/src/query/__tests__/window-functions.test.ts +0 -275
  63. package/src/query/index.ts +0 -7
  64. package/src/query/query-ast.ts +0 -341
  65. package/src/registry/PluginScopeImpl.ts +0 -259
  66. package/src/registry/PluginSystem.ts +0 -206
  67. package/src/registry/Registry.ts +0 -219
  68. package/src/registry/WidgetRegistry.ts +0 -316
  69. package/src/registry/__tests__/PluginSystem.test.ts +0 -309
  70. package/src/registry/__tests__/Registry.test.ts +0 -293
  71. package/src/registry/__tests__/WidgetRegistry.test.ts +0 -321
  72. package/src/registry/__tests__/plugin-scope-integration.test.ts +0 -283
  73. package/src/theme/ThemeEngine.ts +0 -530
  74. package/src/theme/__tests__/ThemeEngine.test.ts +0 -668
  75. package/src/theme/index.ts +0 -24
  76. package/src/types/index.ts +0 -21
  77. package/src/utils/__tests__/debug-collector.test.ts +0 -102
  78. package/src/utils/__tests__/debug.test.ts +0 -134
  79. package/src/utils/__tests__/expand-fields.test.ts +0 -120
  80. package/src/utils/__tests__/extract-records.test.ts +0 -50
  81. package/src/utils/__tests__/filter-converter.test.ts +0 -118
  82. package/src/utils/__tests__/merge-views-into-objects.test.ts +0 -110
  83. package/src/utils/__tests__/normalize-quick-filter.test.ts +0 -123
  84. package/src/utils/debug-collector.ts +0 -100
  85. package/src/utils/debug.ts +0 -148
  86. package/src/utils/expand-fields.ts +0 -76
  87. package/src/utils/extract-records.ts +0 -33
  88. package/src/utils/filter-converter.ts +0 -133
  89. package/src/utils/merge-views-into-objects.ts +0 -36
  90. package/src/utils/normalize-quick-filter.ts +0 -78
  91. package/src/validation/__tests__/object-validation-engine.test.ts +0 -567
  92. package/src/validation/__tests__/schema-validator.test.ts +0 -118
  93. package/src/validation/__tests__/validation-engine.test.ts +0 -102
  94. package/src/validation/index.ts +0 -10
  95. package/src/validation/schema-validator.ts +0 -344
  96. package/src/validation/validation-engine.ts +0 -528
  97. package/src/validation/validators/index.ts +0 -25
  98. package/src/validation/validators/object-validation-engine.ts +0 -722
  99. package/tsconfig.json +0 -15
  100. package/tsconfig.tsbuildinfo +0 -1
  101. package/vitest.config.ts +0 -2
@@ -1,181 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
-
9
- /**
10
- * @object-ui/core - Keyboard Protocol Bridge
11
- *
12
- * Converts spec-aligned keyboard navigation and focus management
13
- * schemas into runtime-usable configurations, shortcut parsers,
14
- * and focus trap settings.
15
- *
16
- * @module protocols/KeyboardProtocol
17
- * @packageDocumentation
18
- */
19
-
20
- import type {
21
- KeyboardNavigationConfig,
22
- KeyboardShortcut,
23
- FocusManagement,
24
- FocusTrapConfig,
25
- } from '@object-ui/types';
26
-
27
- // ============================================================================
28
- // Resolved Types
29
- // ============================================================================
30
-
31
- /** Fully resolved keyboard navigation configuration. */
32
- export interface ResolvedKeyboardConfig {
33
- shortcuts: KeyboardShortcut[];
34
- focusManagement: ResolvedFocusManagement;
35
- rovingTabindex: boolean;
36
- ariaLabel?: string;
37
- ariaDescribedBy?: string;
38
- role?: string;
39
- }
40
-
41
- /** Fully resolved focus management configuration. */
42
- export interface ResolvedFocusManagement {
43
- tabOrder: 'auto' | 'manual';
44
- skipLinks: boolean;
45
- focusVisible: boolean;
46
- focusTrap?: ResolvedFocusTrapConfig;
47
- arrowNavigation: boolean;
48
- }
49
-
50
- /** Fully resolved focus trap configuration. */
51
- export interface ResolvedFocusTrapConfig {
52
- enabled: boolean;
53
- initialFocus?: string;
54
- returnFocus: boolean;
55
- escapeDeactivates: boolean;
56
- }
57
-
58
- /** Parsed keyboard shortcut descriptor. */
59
- export interface ParsedShortcut {
60
- key: string;
61
- ctrlOrMeta: boolean;
62
- shift: boolean;
63
- alt: boolean;
64
- }
65
-
66
- /** Minimal keyboard event shape for matching (no React dependency). */
67
- export interface KeyboardEventLike {
68
- key: string;
69
- ctrlKey?: boolean;
70
- metaKey?: boolean;
71
- shiftKey?: boolean;
72
- altKey?: boolean;
73
- }
74
-
75
- // ============================================================================
76
- // Keyboard Config Resolution
77
- // ============================================================================
78
-
79
- /**
80
- * Resolve a keyboard navigation configuration by applying spec defaults.
81
- *
82
- * @param config - KeyboardNavigationConfig from the spec
83
- * @returns Fully resolved keyboard navigation configuration
84
- */
85
- export function resolveKeyboardConfig(config: KeyboardNavigationConfig): ResolvedKeyboardConfig {
86
- return {
87
- shortcuts: config.shortcuts ?? [],
88
- focusManagement: resolveFocusManagement(config.focusManagement),
89
- rovingTabindex: config.rovingTabindex ?? false,
90
- ariaLabel: config.ariaLabel,
91
- ariaDescribedBy: config.ariaDescribedBy,
92
- role: config.role,
93
- };
94
- }
95
-
96
- /**
97
- * Resolve focus management configuration with defaults.
98
- */
99
- function resolveFocusManagement(fm?: FocusManagement): ResolvedFocusManagement {
100
- return {
101
- tabOrder: fm?.tabOrder ?? 'auto',
102
- skipLinks: fm?.skipLinks ?? false,
103
- focusVisible: fm?.focusVisible ?? true,
104
- focusTrap: fm?.focusTrap ? createFocusTrapConfig(fm.focusTrap) : undefined,
105
- arrowNavigation: fm?.arrowNavigation ?? false,
106
- };
107
- }
108
-
109
- // ============================================================================
110
- // Shortcut Parsing
111
- // ============================================================================
112
-
113
- /**
114
- * Parse a shortcut string like "Ctrl+Shift+S" into a structured descriptor.
115
- * Recognises Ctrl, Meta, Cmd (mapped to ctrlOrMeta), Shift, and Alt modifiers.
116
- * The last segment is treated as the key.
117
- *
118
- * Keys are normalised to lowercase for case-insensitive matching. The Shift
119
- * modifier is tracked separately, so "Shift+A" and "Shift+a" are equivalent
120
- * (both represent the same physical key combination).
121
- *
122
- * @param shortcut - Shortcut string (e.g. "Ctrl+S", "Alt+Shift+N", "Escape")
123
- * @returns Parsed shortcut descriptor
124
- */
125
- export function parseShortcutKey(shortcut: string): ParsedShortcut {
126
- const parts = shortcut.split('+').map(p => p.trim());
127
- const modifiers = new Set(parts.slice(0, -1).map(m => m.toLowerCase()));
128
- const key = (parts[parts.length - 1] ?? '').toLowerCase();
129
-
130
- return {
131
- key,
132
- ctrlOrMeta: modifiers.has('ctrl') || modifiers.has('meta') || modifiers.has('cmd'),
133
- shift: modifiers.has('shift'),
134
- alt: modifiers.has('alt'),
135
- };
136
- }
137
-
138
- // ============================================================================
139
- // Shortcut Matching
140
- // ============================================================================
141
-
142
- /**
143
- * Test whether a keyboard event matches a shortcut string.
144
- * Comparison is case-insensitive; the Shift modifier is checked separately.
145
- *
146
- * @param event - The keyboard event (or a plain object with key + modifier flags)
147
- * @param shortcut - Shortcut string (e.g. "Ctrl+S")
148
- * @returns `true` if the event matches the shortcut
149
- */
150
- export function matchesShortcut(event: KeyboardEventLike, shortcut: string): boolean {
151
- const parsed = parseShortcutKey(shortcut);
152
-
153
- if (event.key.toLowerCase() !== parsed.key) return false;
154
-
155
- const eventCtrlOrMeta = !!(event.ctrlKey || event.metaKey);
156
- if (parsed.ctrlOrMeta !== eventCtrlOrMeta) return false;
157
-
158
- if (parsed.shift !== !!(event.shiftKey)) return false;
159
- if (parsed.alt !== !!(event.altKey)) return false;
160
-
161
- return true;
162
- }
163
-
164
- // ============================================================================
165
- // Focus Trap Configuration
166
- // ============================================================================
167
-
168
- /**
169
- * Create a resolved focus trap configuration from a spec FocusTrapConfig.
170
- *
171
- * @param config - FocusTrapConfig from the spec
172
- * @returns Resolved focus trap configuration with defaults applied
173
- */
174
- export function createFocusTrapConfig(config: FocusTrapConfig): ResolvedFocusTrapConfig {
175
- return {
176
- enabled: config.enabled ?? false,
177
- initialFocus: config.initialFocus,
178
- returnFocus: config.returnFocus ?? true,
179
- escapeDeactivates: config.escapeDeactivates ?? true,
180
- };
181
- }
@@ -1,150 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
-
9
- /**
10
- * @object-ui/core - Notification Protocol Bridge
11
- *
12
- * Converts spec-aligned Notification schemas into toast-compatible
13
- * objects that UI layers can render. Maps severity to variant,
14
- * position names, and resolves default notification configs.
15
- *
16
- * @module protocols/NotificationProtocol
17
- * @packageDocumentation
18
- */
19
-
20
- import type {
21
- Notification as SpecNotification,
22
- NotificationAction,
23
- NotificationConfig,
24
- NotificationPosition,
25
- NotificationSeverity,
26
- } from '@object-ui/types';
27
-
28
- // ============================================================================
29
- // Resolved Types
30
- // ============================================================================
31
-
32
- /** Fully resolved notification configuration. */
33
- export interface ResolvedNotificationConfig {
34
- defaultPosition: NotificationPosition;
35
- defaultDuration: number;
36
- maxVisible: number;
37
- stackDirection: 'up' | 'down';
38
- pauseOnHover: boolean;
39
- }
40
-
41
- /** Toast-compatible representation of a spec Notification. */
42
- export interface ToastNotification {
43
- title?: string;
44
- description: string;
45
- variant: string;
46
- position: string;
47
- duration: number;
48
- dismissible: boolean;
49
- actions: ToastAction[];
50
- }
51
-
52
- /** Toast-compatible action button. */
53
- export interface ToastAction {
54
- label: string;
55
- action: string;
56
- variant: 'primary' | 'secondary' | 'link';
57
- }
58
-
59
- // ============================================================================
60
- // Severity → Variant Mapping
61
- // ============================================================================
62
-
63
- const SEVERITY_TO_VARIANT: Record<string, string> = {
64
- info: 'default',
65
- success: 'success',
66
- warning: 'warning',
67
- error: 'destructive',
68
- };
69
-
70
- /**
71
- * Map a spec notification severity to a toast variant string.
72
- *
73
- * @param severity - Spec severity (info, success, warning, error)
74
- * @returns Toast variant (default, success, warning, destructive)
75
- */
76
- export function mapSeverityToVariant(severity: string): string {
77
- return SEVERITY_TO_VARIANT[severity] ?? 'default';
78
- }
79
-
80
- // ============================================================================
81
- // Position Mapping
82
- // ============================================================================
83
-
84
- const POSITION_MAP: Record<string, string> = {
85
- top_left: 'top-left',
86
- top_center: 'top-center',
87
- top_right: 'top-right',
88
- bottom_left: 'bottom-left',
89
- bottom_center: 'bottom-center',
90
- bottom_right: 'bottom-right',
91
- };
92
-
93
- /**
94
- * Map a spec notification position (underscore-separated) to a
95
- * toast position string (hyphen-separated).
96
- *
97
- * @param position - Spec position (e.g. "top_right")
98
- * @returns Toast position (e.g. "top-right")
99
- */
100
- export function mapPosition(position: string): string {
101
- return POSITION_MAP[position] ?? 'top-right';
102
- }
103
-
104
- // ============================================================================
105
- // Notification Config Resolution
106
- // ============================================================================
107
-
108
- /**
109
- * Resolve a notification configuration by applying spec defaults.
110
- *
111
- * @param config - NotificationConfig from the spec
112
- * @returns Fully resolved notification configuration
113
- */
114
- export function resolveNotificationConfig(config: NotificationConfig): ResolvedNotificationConfig {
115
- return {
116
- defaultPosition: config.defaultPosition ?? 'top_right',
117
- defaultDuration: config.defaultDuration ?? 5000,
118
- maxVisible: config.maxVisible ?? 5,
119
- stackDirection: config.stackDirection ?? 'down',
120
- pauseOnHover: config.pauseOnHover ?? true,
121
- };
122
- }
123
-
124
- // ============================================================================
125
- // Spec Notification → Toast
126
- // ============================================================================
127
-
128
- /**
129
- * Convert a spec Notification to a toast-compatible object.
130
- *
131
- * @param notification - Spec Notification
132
- * @returns Toast-compatible notification with title, description, variant, etc.
133
- */
134
- export function specNotificationToToast(notification: SpecNotification): ToastNotification {
135
- const actions: ToastAction[] = (notification.actions ?? []).map((a: NotificationAction) => ({
136
- label: a.label,
137
- action: a.action,
138
- variant: a.variant ?? 'primary',
139
- }));
140
-
141
- return {
142
- title: notification.title,
143
- description: notification.message ?? '',
144
- variant: mapSeverityToVariant(notification.severity ?? 'info'),
145
- position: mapPosition(notification.position ?? 'top_right'),
146
- duration: notification.duration ?? 5000,
147
- dismissible: notification.dismissible ?? true,
148
- actions,
149
- };
150
- }
@@ -1,210 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
-
9
- /**
10
- * @object-ui/core - Responsive Protocol Bridge
11
- *
12
- * Converts spec-aligned ResponsiveConfig schemas into Tailwind CSS
13
- * utility classes for visibility, grid columns, and ordering across
14
- * breakpoints. Also provides runtime width-based visibility checks.
15
- *
16
- * @module protocols/ResponsiveProtocol
17
- * @packageDocumentation
18
- */
19
-
20
- import type { SpecResponsiveConfig } from '@object-ui/types';
21
-
22
- // ============================================================================
23
- // Breakpoint Definitions
24
- // ============================================================================
25
-
26
- /** Breakpoint name type matching Tailwind defaults. */
27
- export type BreakpointKey = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
28
-
29
- /** Breakpoint minimum pixel widths aligned with Tailwind CSS defaults. */
30
- export const BREAKPOINT_VALUES: Record<BreakpointKey, number> = {
31
- xs: 0,
32
- sm: 640,
33
- md: 768,
34
- lg: 1024,
35
- xl: 1280,
36
- '2xl': 1536,
37
- };
38
-
39
- /** Ordered breakpoint keys from smallest to largest. */
40
- const BREAKPOINT_ORDER: BreakpointKey[] = ['xs', 'sm', 'md', 'lg', 'xl', '2xl'];
41
-
42
- // ============================================================================
43
- // Resolved Types
44
- // ============================================================================
45
-
46
- /** Fully resolved responsive configuration. */
47
- export interface ResolvedResponsiveConfig {
48
- breakpoint?: BreakpointKey;
49
- hiddenOn: BreakpointKey[];
50
- columns: Partial<Record<BreakpointKey, number>>;
51
- order: Partial<Record<BreakpointKey, number>>;
52
- }
53
-
54
- // ============================================================================
55
- // Config Resolution
56
- // ============================================================================
57
-
58
- /**
59
- * Resolve a responsive configuration by applying defaults.
60
- *
61
- * @param config - SpecResponsiveConfig from the spec
62
- * @returns Fully resolved responsive configuration
63
- */
64
- export function resolveResponsiveConfig(config: SpecResponsiveConfig): ResolvedResponsiveConfig {
65
- return {
66
- breakpoint: config.breakpoint as BreakpointKey | undefined,
67
- hiddenOn: (config.hiddenOn ?? []) as BreakpointKey[],
68
- columns: (config.columns ?? {}) as Partial<Record<BreakpointKey, number>>,
69
- order: (config.order ?? {}) as Partial<Record<BreakpointKey, number>>,
70
- };
71
- }
72
-
73
- // ============================================================================
74
- // Visibility Classes
75
- // ============================================================================
76
-
77
- /**
78
- * Generate Tailwind CSS classes for responsive visibility.
79
- *
80
- * If `breakpoint` is set, the element is hidden below that breakpoint
81
- * (e.g. breakpoint "md" → `['hidden', 'md:block']`).
82
- *
83
- * If `hiddenOn` contains breakpoints, the element is hidden at those
84
- * specific sizes (e.g. hiddenOn: ["sm", "lg"] → `['sm:hidden', 'md:block', 'lg:hidden', 'xl:block']`).
85
- *
86
- * @param config - SpecResponsiveConfig from the spec
87
- * @returns Array of Tailwind CSS class strings
88
- */
89
- export function getVisibilityClasses(config: SpecResponsiveConfig): string[] {
90
- const classes: string[] = [];
91
-
92
- // Minimum breakpoint visibility
93
- if (config.breakpoint) {
94
- const bp = config.breakpoint as BreakpointKey;
95
- if (bp !== 'xs') {
96
- classes.push('hidden');
97
- classes.push(`${bp}:block`);
98
- }
99
- }
100
-
101
- // Per-breakpoint hidden overrides
102
- const hiddenOn = (config.hiddenOn ?? []) as BreakpointKey[];
103
- if (hiddenOn.length > 0) {
104
- for (let i = 0; i < BREAKPOINT_ORDER.length; i++) {
105
- const bp = BREAKPOINT_ORDER[i];
106
- const isHidden = hiddenOn.includes(bp);
107
- const prevHidden = i > 0 ? hiddenOn.includes(BREAKPOINT_ORDER[i - 1]) : false;
108
-
109
- if (isHidden && !prevHidden) {
110
- classes.push(bp === 'xs' ? 'hidden' : `${bp}:hidden`);
111
- } else if (!isHidden && prevHidden) {
112
- classes.push(bp === 'xs' ? 'block' : `${bp}:block`);
113
- }
114
- }
115
- }
116
-
117
- return classes;
118
- }
119
-
120
- // ============================================================================
121
- // Column Classes
122
- // ============================================================================
123
-
124
- /**
125
- * Generate Tailwind grid-cols classes for responsive column layouts.
126
- *
127
- * @param config - SpecResponsiveConfig from the spec
128
- * @returns Array of Tailwind CSS grid column class strings
129
- */
130
- export function getColumnClasses(config: SpecResponsiveConfig): string[] {
131
- const classes: string[] = [];
132
- const columns = (config.columns ?? {}) as Partial<Record<BreakpointKey, number>>;
133
-
134
- for (const bp of BREAKPOINT_ORDER) {
135
- const cols = columns[bp];
136
- if (cols == null) continue;
137
- const prefix = bp === 'xs' ? '' : `${bp}:`;
138
- classes.push(`${prefix}grid-cols-${cols}`);
139
- }
140
-
141
- return classes;
142
- }
143
-
144
- // ============================================================================
145
- // Order Classes
146
- // ============================================================================
147
-
148
- /**
149
- * Generate Tailwind order utility classes for responsive ordering.
150
- *
151
- * @param config - SpecResponsiveConfig from the spec
152
- * @returns Array of Tailwind CSS order class strings
153
- */
154
- export function getOrderClasses(config: SpecResponsiveConfig): string[] {
155
- const classes: string[] = [];
156
- const order = (config.order ?? {}) as Partial<Record<BreakpointKey, number>>;
157
-
158
- for (const bp of BREAKPOINT_ORDER) {
159
- const ord = order[bp];
160
- if (ord == null) continue;
161
- const prefix = bp === 'xs' ? '' : `${bp}:`;
162
- classes.push(`${prefix}order-${ord}`);
163
- }
164
-
165
- return classes;
166
- }
167
-
168
- // ============================================================================
169
- // Runtime Width Check
170
- // ============================================================================
171
-
172
- /**
173
- * Determine whether a component should be hidden at a given viewport width.
174
- *
175
- * Checks both the minimum `breakpoint` threshold and the `hiddenOn` list.
176
- *
177
- * @param config - SpecResponsiveConfig from the spec
178
- * @param width - Current viewport width in pixels
179
- * @returns `true` if the component should be hidden at the given width
180
- */
181
- export function shouldHideAtBreakpoint(config: SpecResponsiveConfig, width: number): boolean {
182
- // Check minimum breakpoint
183
- if (config.breakpoint) {
184
- const minWidth = BREAKPOINT_VALUES[config.breakpoint as BreakpointKey];
185
- if (minWidth !== undefined && width < minWidth) {
186
- return true;
187
- }
188
- }
189
-
190
- // Check hiddenOn list
191
- const hiddenOn = (config.hiddenOn ?? []) as BreakpointKey[];
192
- if (hiddenOn.length > 0) {
193
- const currentBp = getCurrentBreakpoint(width);
194
- return hiddenOn.includes(currentBp);
195
- }
196
-
197
- return false;
198
- }
199
-
200
- /**
201
- * Determine the current breakpoint name for a given width.
202
- */
203
- function getCurrentBreakpoint(width: number): BreakpointKey {
204
- for (let i = BREAKPOINT_ORDER.length - 1; i >= 0; i--) {
205
- if (width >= BREAKPOINT_VALUES[BREAKPOINT_ORDER[i]]) {
206
- return BREAKPOINT_ORDER[i];
207
- }
208
- }
209
- return 'xs';
210
- }