@shohojdhara/atomix 0.3.14 → 0.3.15

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 (173) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/build-tools/EXAMPLES.md +372 -0
  3. package/build-tools/README.md +242 -0
  4. package/build-tools/__tests__/error-handler.test.js +230 -0
  5. package/build-tools/__tests__/index.test.js +141 -0
  6. package/build-tools/__tests__/rollup-plugin.test.js +194 -0
  7. package/build-tools/__tests__/utils.test.js +161 -0
  8. package/build-tools/__tests__/vite-plugin.test.js +129 -0
  9. package/build-tools/__tests__/webpack-loader.test.js +190 -0
  10. package/build-tools/error-handler.js +308 -0
  11. package/build-tools/index.d.ts +43 -0
  12. package/build-tools/index.js +88 -0
  13. package/build-tools/package.json +67 -0
  14. package/build-tools/rollup-plugin.js +236 -0
  15. package/build-tools/types.d.ts +163 -0
  16. package/build-tools/utils.js +203 -0
  17. package/build-tools/vite-plugin.js +161 -0
  18. package/build-tools/webpack-loader.js +123 -0
  19. package/dist/atomix.css +203 -90
  20. package/dist/atomix.css.map +1 -1
  21. package/dist/atomix.min.css +3 -3
  22. package/dist/atomix.min.css.map +1 -1
  23. package/dist/build-tools/EXAMPLES.md +372 -0
  24. package/dist/build-tools/README.md +242 -0
  25. package/dist/build-tools/__tests__/error-handler.test.js +230 -0
  26. package/dist/build-tools/__tests__/index.test.js +141 -0
  27. package/dist/build-tools/__tests__/rollup-plugin.test.js +194 -0
  28. package/dist/build-tools/__tests__/utils.test.js +161 -0
  29. package/dist/build-tools/__tests__/vite-plugin.test.js +129 -0
  30. package/dist/build-tools/__tests__/webpack-loader.test.js +190 -0
  31. package/dist/build-tools/error-handler.js +308 -0
  32. package/dist/build-tools/index.d.ts +43 -0
  33. package/dist/build-tools/index.js +88 -0
  34. package/dist/build-tools/package.json +67 -0
  35. package/dist/build-tools/rollup-plugin.js +236 -0
  36. package/dist/build-tools/types.d.ts +163 -0
  37. package/dist/build-tools/utils.js +203 -0
  38. package/dist/build-tools/vite-plugin.js +161 -0
  39. package/dist/build-tools/webpack-loader.js +123 -0
  40. package/dist/charts.d.ts +1 -1
  41. package/dist/charts.js +86 -57
  42. package/dist/charts.js.map +1 -1
  43. package/dist/core.d.ts +1 -1
  44. package/dist/core.js +136 -112
  45. package/dist/core.js.map +1 -1
  46. package/dist/forms.d.ts +2 -5
  47. package/dist/forms.js +140 -128
  48. package/dist/forms.js.map +1 -1
  49. package/dist/heavy.d.ts +1 -1
  50. package/dist/heavy.js +136 -112
  51. package/dist/heavy.js.map +1 -1
  52. package/dist/index.d.ts +9 -61
  53. package/dist/index.esm.js +237 -286
  54. package/dist/index.esm.js.map +1 -1
  55. package/dist/index.js +250 -299
  56. package/dist/index.js.map +1 -1
  57. package/dist/index.min.js +1 -1
  58. package/dist/index.min.js.map +1 -1
  59. package/package.json +23 -8
  60. package/scripts/atomix-cli.js +170 -73
  61. package/scripts/cli/__tests__/README.md +81 -0
  62. package/scripts/cli/__tests__/basic.test.js +115 -0
  63. package/scripts/cli/__tests__/component-generator.test.js +332 -0
  64. package/scripts/cli/__tests__/integration.test.js +327 -0
  65. package/scripts/cli/__tests__/test-setup.js +133 -0
  66. package/scripts/cli/__tests__/token-manager.test.js +251 -0
  67. package/scripts/cli/__tests__/utils.test.js +161 -0
  68. package/scripts/cli/component-generator.js +253 -299
  69. package/scripts/cli/dependency-checker.js +355 -0
  70. package/scripts/cli/interactive-init.js +46 -5
  71. package/scripts/cli/template-manager.js +0 -2
  72. package/scripts/cli/templates/common-templates.js +636 -0
  73. package/scripts/cli/templates/composable-templates.js +148 -126
  74. package/scripts/cli/templates/index.js +23 -16
  75. package/scripts/cli/templates/project-templates.js +151 -23
  76. package/scripts/cli/templates/react-templates.js +280 -210
  77. package/scripts/cli/templates/scss-templates.js +90 -91
  78. package/scripts/cli/templates/testing-templates.js +206 -27
  79. package/scripts/cli/templates/testing-utils.js +278 -0
  80. package/scripts/cli/templates/types-templates.js +70 -56
  81. package/scripts/cli/theme-bridge.js +8 -2
  82. package/scripts/cli/token-manager.js +318 -206
  83. package/scripts/cli/utils.js +0 -1
  84. package/src/components/Accordion/Accordion.stories.tsx +369 -870
  85. package/src/components/AtomixGlass/AtomixGlass.tsx +80 -39
  86. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +103 -81
  87. package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +8 -7
  88. package/src/components/AtomixGlass/glass-utils.ts +2 -2
  89. package/src/components/AtomixGlass/shader-utils.ts +5 -0
  90. package/src/components/AtomixGlass/stories/Customization.stories.tsx +131 -0
  91. package/src/components/AtomixGlass/stories/Examples.stories.tsx +2957 -2853
  92. package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -1
  93. package/src/components/AtomixGlass/stories/Overview.stories.tsx +348 -0
  94. package/src/components/AtomixGlass/stories/Performance.stories.tsx +103 -0
  95. package/src/components/AtomixGlass/stories/Playground.stories.tsx +50 -35
  96. package/src/components/AtomixGlass/stories/{ShaderVariants.stories.tsx → Shaders.stories.tsx} +1 -1
  97. package/src/components/AtomixGlass/stories/shared-components.tsx +90 -190
  98. package/src/components/Avatar/Avatar.stories.tsx +213 -1
  99. package/src/components/Badge/Badge.stories.tsx +121 -362
  100. package/src/components/Block/Block.stories.tsx +21 -12
  101. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +141 -23
  102. package/src/components/Button/Button.stories.tsx +463 -1126
  103. package/src/components/Button/Button.test.tsx +107 -0
  104. package/src/components/Button/Button.tsx +46 -50
  105. package/src/components/Button/ButtonGroup.stories.tsx +373 -217
  106. package/src/components/Callout/Callout.stories.tsx +289 -634
  107. package/src/components/Card/Card.stories.tsx +248 -68
  108. package/src/components/Chart/Chart.stories.tsx +150 -8
  109. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +151 -69
  110. package/src/components/Countdown/Countdown.stories.tsx +115 -8
  111. package/src/components/DataTable/DataTable.stories.tsx +346 -146
  112. package/src/components/DatePicker/DatePicker.stories.tsx +325 -1066
  113. package/src/components/Dropdown/Dropdown.stories.tsx +153 -33
  114. package/src/components/EdgePanel/EdgePanel.stories.tsx +230 -21
  115. package/src/components/Footer/Footer.stories.tsx +392 -328
  116. package/src/components/Form/Checkbox.stories.tsx +140 -6
  117. package/src/components/Form/Checkbox.test.tsx +63 -0
  118. package/src/components/Form/Checkbox.tsx +87 -51
  119. package/src/components/Form/Form.stories.tsx +119 -20
  120. package/src/components/Form/FormGroup.stories.tsx +127 -4
  121. package/src/components/Form/Radio.stories.tsx +140 -5
  122. package/src/components/Form/Select.stories.tsx +140 -8
  123. package/src/components/Form/Textarea.stories.tsx +149 -6
  124. package/src/components/Hero/Hero.stories.tsx +333 -32
  125. package/src/components/List/List.stories.tsx +141 -3
  126. package/src/components/Modal/Modal.stories.tsx +181 -42
  127. package/src/components/Popover/Popover.stories.tsx +448 -98
  128. package/src/components/Progress/Progress.stories.tsx +167 -5
  129. package/src/components/River/River.stories.tsx +1 -1
  130. package/src/components/SectionIntro/SectionIntro.stories.tsx +240 -48
  131. package/src/components/Spinner/Spinner.stories.tsx +102 -8
  132. package/src/components/Steps/Steps.stories.tsx +172 -43
  133. package/src/components/Tabs/Tabs.stories.tsx +136 -10
  134. package/src/components/Testimonial/Testimonial.stories.tsx +120 -3
  135. package/src/components/Todo/Todo.stories.tsx +198 -9
  136. package/src/components/Toggle/Toggle.stories.tsx +126 -39
  137. package/src/components/Tooltip/Tooltip.stories.tsx +194 -104
  138. package/src/components/Upload/Upload.stories.tsx +113 -24
  139. package/src/lib/README.md +2 -2
  140. package/src/lib/__tests__/theme-tools.test.ts +193 -0
  141. package/src/lib/composables/index.ts +2 -2
  142. package/src/lib/composables/useAtomixGlass.ts +28 -56
  143. package/src/lib/composables/useChartExport.ts +2 -7
  144. package/src/lib/composables/useDataTable.ts +46 -29
  145. package/src/lib/constants/components.ts +9 -32
  146. package/src/lib/theme/devtools/CLI.ts +1 -1
  147. package/src/lib/types/components.ts +1 -1
  148. package/src/lib/utils/__tests__/csv.test.ts +45 -0
  149. package/src/lib/utils/csv.ts +17 -0
  150. package/src/lib/utils/dataTableExport.ts +1 -10
  151. package/src/styles/01-settings/_index.scss +2 -1
  152. package/src/styles/01-settings/_settings.accordion.scss +28 -7
  153. package/src/styles/01-settings/_settings.colors.scss +11 -11
  154. package/src/styles/01-settings/_settings.typography.scss +5 -5
  155. package/src/styles/02-tools/_tools.utility-api.scss +14 -0
  156. package/src/styles/06-components/_components.accordion.scss +56 -14
  157. package/src/styles/06-components/_components.checkbox.scss +23 -17
  158. package/src/styles/99-utilities/_index.scss +2 -0
  159. package/src/styles/99-utilities/_utilities.scss +3 -1
  160. package/src/styles/99-utilities/_utilities.text-gradient.scss +45 -0
  161. package/themes/dark-complementary/README.md +98 -0
  162. package/themes/dark-complementary/index.scss +158 -0
  163. package/themes/default-light/README.md +81 -0
  164. package/themes/default-light/index.scss +154 -0
  165. package/themes/high-contrast/README.md +105 -0
  166. package/themes/high-contrast/index.scss +172 -0
  167. package/themes/test-theme/README.md +38 -0
  168. package/themes/test-theme/index.scss +47 -0
  169. package/scripts/cli/templates-original-backup.js +0 -1655
  170. package/scripts/cli/templates_backup.js +0 -684
  171. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +0 -1438
  172. package/src/lib/composables/useButton.ts +0 -93
  173. package/src/lib/composables/useCheckbox.ts +0 -70
@@ -328,47 +328,64 @@ export function useDataTable({
328
328
  setCurrentPage(1);
329
329
  }, []);
330
330
 
331
+ // Pre-process column filters to avoid redundant lookups and transformations
332
+ const activeColumnFilters = useMemo(() => {
333
+ if (!columnFilters) return [];
334
+
335
+ return Object.entries(columnFilterValues)
336
+ .filter(([, value]) => value !== undefined && value !== null && value !== '')
337
+ .map(([columnKey, value]) => {
338
+ const column = columns.find(col => col.key === columnKey);
339
+ if (!column || !column.filterable) return null;
340
+
341
+ return {
342
+ key: columnKey,
343
+ value,
344
+ lowercaseValue: typeof value === 'string' ? value.toLowerCase() : String(value).toLowerCase(),
345
+ column,
346
+ };
347
+ })
348
+ .filter((f): f is NonNullable<typeof f> => f !== null);
349
+ }, [columnFilters, columnFilterValues, columns]);
350
+
331
351
  // Filter data based on search query and column filters
332
352
  const filteredData = useMemo(() => {
333
- let result = data;
353
+ if (!searchQuery && activeColumnFilters.length === 0) {
354
+ return data;
355
+ }
334
356
 
335
- // Apply global search
336
- if (searchQuery) {
337
- const lowercaseQuery = searchQuery.toLowerCase();
338
- result = result.filter(row => {
339
- return visibleColumns.some(column => {
357
+ const lowercaseQuery = searchQuery ? searchQuery.toLowerCase() : '';
358
+
359
+ return data.filter(row => {
360
+ // Apply global search
361
+ if (searchQuery) {
362
+ const matchesGlobal = visibleColumns.some(column => {
340
363
  const value = row[column.key];
341
364
  if (value == null) return false;
342
365
  return String(value).toLowerCase().includes(lowercaseQuery);
343
366
  });
344
- });
345
- }
346
-
347
- // Apply column-specific filters
348
- if (columnFilters) {
349
- result = result.filter(row => {
350
- return Object.entries(columnFilterValues).every(([columnKey, filterValue]) => {
351
- if (!filterValue) return true;
352
-
353
- const column = columns.find(col => col.key === columnKey);
354
- if (!column || !column.filterable) return true;
367
+ if (!matchesGlobal) return false;
368
+ }
355
369
 
356
- const cellValue = row[columnKey];
357
- if (cellValue == null) return false;
370
+ // Apply column-specific filters
371
+ for (let i = 0; i < activeColumnFilters.length; i++) {
372
+ const { key, value, lowercaseValue, column } = activeColumnFilters[i];
373
+ const cellValue = row[key];
358
374
 
359
- // Use custom filter function if provided
360
- if (column.filterFunction) {
361
- return column.filterFunction(cellValue, filterValue);
362
- }
375
+ if (cellValue == null) return false;
363
376
 
377
+ // Use custom filter function if provided
378
+ if (column.filterFunction) {
379
+ if (!column.filterFunction(cellValue, value)) return false;
380
+ } else {
364
381
  // Default text filter
365
- return String(cellValue).toLowerCase().includes(filterValue.toLowerCase());
366
- });
367
- });
368
- }
382
+ if (!String(cellValue).toLowerCase().includes(lowercaseValue)) return false;
383
+ }
384
+ }
369
385
 
370
- return result;
371
- }, [data, visibleColumns, searchQuery, columnFilterValues, columnFilters, columns]);
386
+ return true;
387
+ });
388
+ }, [data, visibleColumns, searchQuery, activeColumnFilters]);
372
389
 
373
390
  // Sort data
374
391
  const sortedData = useMemo(() => {
@@ -1522,37 +1522,6 @@ export const BLOCK = {
1522
1522
  },
1523
1523
  };
1524
1524
 
1525
- /**
1526
- * GlassContainer-specific constants
1527
- */
1528
- export const GLASS_CONTAINER = {
1529
- CLASSES: {
1530
- BASE: 'c-glass-container',
1531
- GLASS: 'c-glass-container__glass',
1532
- WARP: 'c-glass-container__warp',
1533
- CONTENT: 'c-glass-container__content',
1534
- OVERLAY: 'c-glass-container__overlay',
1535
- OVERLAY_VISIBLE: 'c-glass-container__overlay--visible',
1536
- OVERLAY_HIDDEN: 'c-glass-container__overlay--hidden',
1537
- OVERLAY_BLEND: 'c-glass-container__overlay-blend',
1538
- BORDER: 'c-glass-container__border',
1539
- BORDER_OVERLAY: 'c-glass-container__border-overlay',
1540
- HOVER_EFFECT: 'c-glass-container__hover-effect',
1541
- ACTIVE_EFFECT: 'c-glass-container__active-effect',
1542
- INTERACTION_EFFECT: 'c-glass-container__interaction-effect',
1543
- ACTIVE: 'c-glass-container--active',
1544
- CLICKABLE: 'c-glass-container--clickable',
1545
- },
1546
- DISPLACEMENT_MAPS: {
1547
- STANDARD:
1548
- 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjcwIiBoZWlnaHQ9IjY5IiB2aWV3Qm94PSIwIDAgMjcwIDY5IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxyYWRpYWxHcmFkaWVudCBpZD0iZ3JhZGllbnQiIGN4PSI1MCUiIGN5PSI1MCUiIHI9IjUwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzgwODA4MCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzgwODA4MCIvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZGllbnQpIi8+PC9zdmc+',
1549
- POLAR:
1550
- 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjcwIiBoZWlnaHQ9IjY5IiB2aWV3Qm94PSIwIDAgMjcwIDY5IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxyYWRpYWxHcmFkaWVudCBpZD0icG9sYXIiIGN4PSI1MCUiIGN5PSI1MCUiIHI9IjUwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzQwNDA0MCIvPjxzdG9wIG9mZnNldD0iNTAlIiBzdG9wLWNvbG9yPSIjODA4MDgwIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjNDA0MDQwIi8+PC9yYWRpYWxHcmFkaWVudD48L2RlZnM+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNwb2xhcikiLz48L3N2Zz4=',
1551
- PROMINENT:
1552
- 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjcwIiBoZWlnaHQ9IjY5IiB2aWV3Qm94PSIwIDAgMjcwIDY5IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0icHJvbWluZW50IiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIxMDAlIj48c3RvcCBvZmZzZXQ9IjAlIiBzdG9wLWNvbG9yPSIjNDA0MDQwIi8+PHN0b3Agb2Zmc2V0PSI1MCUiIHN0b3AtY29sb3I9IiNjMGMwYzAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM0MDQwNDAiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI3Byb21pbmVudCkiLz48L3N2Zz4=',
1553
- },
1554
- };
1555
-
1556
1525
  /**
1557
1526
  * Footer-specific constants
1558
1527
  */
@@ -1698,9 +1667,17 @@ export const ATOMIX_GLASS = {
1698
1667
  MIN_BLUR: 0.1,
1699
1668
  MOUSE_INFLUENCE_DIVISOR: 100,
1700
1669
  EDGE_FADE_PIXELS: 2,
1701
- DEFAULT_CORNER_RADIUS: 16, // Fallback value matching design system
1670
+ // Note: This default must match the SCSS variable --atomix-radius-md
1671
+ // @see src/styles/01-settings/_settings.global.scss
1672
+ DEFAULT_CORNER_RADIUS: 16,
1702
1673
  MAX_SIZE: 4096, // Maximum width/height for glass size
1703
1674
 
1675
+ // Palette for internal calculations (matches design system base colors)
1676
+ PALETTE: {
1677
+ WHITE: '255, 255, 255',
1678
+ BLACK: '0, 0, 0',
1679
+ },
1680
+
1704
1681
  // Gradient calculation constants
1705
1682
  GRADIENT: {
1706
1683
  BASE_ANGLE: 135, // Base angle for border gradients (degrees)
@@ -2,7 +2,7 @@
2
2
 
3
3
  /**
4
4
  * Atomix Theme DevTools CLI
5
- *
5
+ *
6
6
  * Internal CLI for theme validation and management.
7
7
  * This is called by the main atomix-cli.js via theme-bridge.js.
8
8
  */
@@ -199,7 +199,7 @@ export interface AtomixGlassProps {
199
199
  /**
200
200
  * Shader variant for shader mode
201
201
  */
202
- shaderVariant?: 'liquidGlass' | 'premiumGlass';
202
+ shaderVariant?: 'liquidGlass' | 'premiumGlass' | 'appleFluid' | 'liquidMetal' | 'plasma' | 'waves' | 'noise';
203
203
 
204
204
  /**
205
205
  * Accessibility props
@@ -0,0 +1,45 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { sanitizeCSVCell } from '../csv';
3
+
4
+ describe('sanitizeCSVCell', () => {
5
+ it('should handle normal strings', () => {
6
+ expect(sanitizeCSVCell('Hello World')).toBe('Hello World');
7
+ expect(sanitizeCSVCell('123')).toBe('123');
8
+ });
9
+
10
+ it('should handle numbers', () => {
11
+ expect(sanitizeCSVCell(123)).toBe('123');
12
+ expect(sanitizeCSVCell(0)).toBe('0');
13
+ // Negative numbers are prefixed with ' to prevent potential formula injection
14
+ expect(sanitizeCSVCell(-1)).toBe("'-1");
15
+ });
16
+
17
+ it('should handle null and undefined', () => {
18
+ expect(sanitizeCSVCell(null)).toBe('');
19
+ expect(sanitizeCSVCell(undefined)).toBe('');
20
+ });
21
+
22
+ it('should replace newlines and tabs with spaces', () => {
23
+ expect(sanitizeCSVCell('Hello\nWorld')).toBe('Hello World');
24
+ expect(sanitizeCSVCell('Hello\rWorld')).toBe('Hello World');
25
+ expect(sanitizeCSVCell('Hello\tWorld')).toBe('Hello World');
26
+ expect(sanitizeCSVCell('Hello\r\nWorld')).toBe('Hello World');
27
+ });
28
+
29
+ it('should escape double quotes', () => {
30
+ expect(sanitizeCSVCell('Hello "World"')).toBe('Hello ""World""');
31
+ expect(sanitizeCSVCell('"')).toBe('""');
32
+ });
33
+
34
+ it('should prevent formula injection', () => {
35
+ expect(sanitizeCSVCell('=SUM(A1:B1)')).toBe("'=SUM(A1:B1)");
36
+ expect(sanitizeCSVCell('+SUM(A1:B1)')).toBe("'+SUM(A1:B1)");
37
+ expect(sanitizeCSVCell('-SUM(A1:B1)')).toBe("'-SUM(A1:B1)");
38
+ expect(sanitizeCSVCell('@SUM(A1:B1)')).toBe("'@SUM(A1:B1)");
39
+ });
40
+
41
+ it('should handle mixed cases', () => {
42
+ // Dangerous character + quotes + newlines
43
+ expect(sanitizeCSVCell('=cmd|\' /C calc\'!A0\n')).toBe("'=cmd|' /C calc'!A0 ");
44
+ });
45
+ });
@@ -0,0 +1,17 @@
1
+ /**
2
+ * CSV Utility Functions
3
+ */
4
+
5
+ /**
6
+ * Sanitize cell content to prevent CSV injection
7
+ *
8
+ * Replaces newlines and tabs with spaces, escapes double quotes,
9
+ * and prefixes dangerous characters (=, +, -, @) with a single quote
10
+ * to prevent formula injection.
11
+ */
12
+ export function sanitizeCSVCell(cell: any): string {
13
+ const sanitized = String(cell ?? '').replace(/[\r\n\t]/g, ' ').replace(/"/g, '""');
14
+ // Prevent formula injection by prefixing dangerous characters
15
+ const dangerous = /^[=+\-@]/;
16
+ return dangerous.test(sanitized) ? `'${sanitized}` : sanitized;
17
+ }
@@ -1,14 +1,5 @@
1
1
  import { DataTableColumn, ExportFormat } from '../types/components';
2
-
3
- /**
4
- * Sanitize cell content to prevent CSV injection
5
- */
6
- function sanitizeCSVCell(cell: any): string {
7
- const sanitized = String(cell ?? '').replace(/[\r\n\t]/g, ' ').replace(/"/g, '""');
8
- // Prevent formula injection by prefixing dangerous characters
9
- const dangerous = /^[=+\-@]/;
10
- return dangerous.test(sanitized) ? `'${sanitized}` : sanitized;
11
- }
2
+ import { sanitizeCSVCell } from './csv';
12
3
 
13
4
  /**
14
5
  * Export data as CSV
@@ -64,4 +64,5 @@
64
64
  @forward './settings.typography';
65
65
  @forward './settings.upload';
66
66
  @forward './settings.video-player';
67
- @forward './settings.z-layers';
67
+ @forward './settings.z-layers';
68
+
@@ -3,30 +3,51 @@
3
3
  @use './settings.config' as config;
4
4
  @use './settings.spacing' as *;
5
5
  @use './settings.colors' as *;
6
+ @use './settings.typography' as *;
6
7
 
8
+ // Accordion dimensions
7
9
  $accordion-width: 100% !default;
8
- $accordion-padding-x: map.get($spacing-sizes, 5) !default;
9
- $accordion-padding-y: map.get($spacing-sizes, 4) !default;
10
+ $accordion-padding-x: map.get($spacing-sizes, 5) !default; //20px
11
+ $accordion-padding-y: map.get($spacing-sizes, 4) !default; //16px
10
12
 
13
+ // Accordion borders
11
14
  $accordion-border-width: calc(var(--#{config.$prefix}border-width) * 2) !default;
12
- $accordion-border-color: transparent !default;
15
+ $accordion-border-color: var(--#{config.$prefix}primary-border-subtle) !default;
13
16
  $accordion-border-radius: radius.$border-radius-sm !default;
14
17
 
18
+ // Accordion body
15
19
  $accordion-body-padding-x: $accordion-padding-x !default;
16
- $accordion-body-padding-y: map.get($spacing-sizes, 2) !default;
20
+ $accordion-body-padding-y: map.get($spacing-sizes, 2) !default; //8px
17
21
  $accordion-body-color: var(--#{config.$prefix}body-color) !default;
18
22
  $accordion-body-bg: var(--#{config.$prefix}body-bg) !default;
19
23
 
24
+ // Accordion header
20
25
  $accordion-header-padding-x: $accordion-padding-x !default;
21
26
  $accordion-header-padding-y: $accordion-padding-y !default;
22
27
  $accordion-header-color: var(--#{config.$prefix}body-color) !default;
23
28
  $accordion-header-bg: var(--#{config.$prefix}body-bg) !default;
24
-
25
29
  $accordion-header-bg-hover: var(--#{config.$prefix}body-bg) !default;
30
+ $accordion-header-font-size: $font-size-base !default;
31
+ $accordion-header-font-weight: $font-weight-normal !default;
26
32
 
27
- $accordion-icon-size: map.get($spacing-sizes, 5) !default;
33
+ // Accordion icon
34
+ $accordion-icon-size: map.get($spacing-sizes, 5) !default; //20px
28
35
  $accordion-icon-color: var(--#{config.$prefix}body-color) !default;
29
-
30
36
  $accordion-icon-transform: 180deg !default;
31
37
 
38
+ // Accordion states
32
39
  $accordion-disable-color: var(--#{config.$prefix}tertiary-text-emphasis) !default;
40
+ $accordion-focus-border-color: var(--#{config.$prefix}focus-border-color) !default;
41
+
42
+ // Accordion transitions
43
+ $accordion-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !default;
44
+ $accordion-panel-transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1) !default;
45
+
46
+ // Accordion spacing
47
+ $accordion-item-gap: 0px !default;
48
+ $accordion-header-inner-gap: map.get($spacing-sizes, 2) !default; //8px
49
+
50
+ // Enable features
51
+ $accordion-enable-glass: true !default;
52
+ $accordion-enable-smooth-scroll: true !default;
53
+ $accordion-enable-focus-ring: true !default;
@@ -11,17 +11,17 @@ $black: #000000 !default;
11
11
  $color-contrast-dark: #000000 !default;
12
12
  $color-contrast-light: #ffffff !default;
13
13
 
14
- // Primitives Primary Colors
15
- $primary-1: #fff9e6 !default;
16
- $primary-2: #fff4cc !default;
17
- $primary-3: #ffe699 !default;
18
- $primary-4: #ffd966 !default;
19
- $primary-5: #ffcc33 !default;
20
- $primary-6: #ffb800 !default; // Balanced primary - main brand color (WCAG AA compliant)
21
- $primary-7: #e6a600 !default;
22
- $primary-8: #cc9400 !default;
23
- $primary-9: #b38200 !default;
24
- $primary-10: #997000 !default;
14
+ // Primitives Primary Colors (Purple Scale)
15
+ $primary-1: #f5f3ff !default;
16
+ $primary-2: #ede9fe !default;
17
+ $primary-3: #ddd6fe !default;
18
+ $primary-4: #c4b5fd !default;
19
+ $primary-5: #a78bfa !default;
20
+ $primary-6: #8b5cf6 !default; // Balanced primary - main brand color (WCAG AA compliant)
21
+ $primary-7: #7c3aed !default;
22
+ $primary-8: #6d28d9 !default;
23
+ $primary-9: #5b21b6 !default;
24
+ $primary-10: #4c1d95 !default;
25
25
 
26
26
  // Primitives Red Colors
27
27
  $red-1: #fef2f2 !default;
@@ -3,7 +3,7 @@
3
3
  // Font, line-height, and color for body text, headings, and more.
4
4
 
5
5
  // Font stacks with appropriate fallbacks
6
- $Roboto: 'Roboto', sans-serif !default;
6
+ $roboto: 'Roboto', sans-serif !default;
7
7
 
8
8
  $helvetica-neue:
9
9
  'Helvetica Neue',
@@ -26,11 +26,11 @@ $system-font-stack:
26
26
  Arial,
27
27
  sans-serif !default;
28
28
 
29
- $font-family-base: $Roboto !default;
30
- $font-family-sans-serif: $Roboto !default;
29
+ $font-family-base: $roboto !default;
30
+ $font-family-sans-serif: $roboto !default;
31
31
  $font-family-monospace:
32
32
  SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace !default;
33
- $headings-font-family: $Roboto !default;
33
+ $headings-font-family: $roboto !default;
34
34
 
35
35
  $font-weight-light: 300 !default;
36
36
  $font-weight-normal: 400 !default;
@@ -92,4 +92,4 @@ $h5-letter-spaceing: -0.5px !default;
92
92
  $h6-letter-spaceing: -0.5px !default;
93
93
 
94
94
  $paragraph-margin-bottom: 0 !default;
95
- $body-text-align: null !default;
95
+ $body-text-align: null !default;
@@ -80,6 +80,13 @@ $utility-defaults: (
80
80
  } @else {
81
81
  #{$property-class}: $value if(map.get($utility, rtl), null, !important);
82
82
  }
83
+
84
+ // Add local CSS variables if specified
85
+ @if map.get($utility, local-vars) {
86
+ @each $local-var-name, $local-var-value in map.get($utility, local-vars) {
87
+ --#{$local-var-name}: #{$local-var-value};
88
+ }
89
+ }
83
90
  }
84
91
  } @else {
85
92
  // Generate class with custom class name
@@ -104,6 +111,13 @@ $utility-defaults: (
104
111
  } @else {
105
112
  #{$base-class}: $value if(map.get($utility, rtl), null, !important);
106
113
  }
114
+
115
+ // Add local CSS variables if specified
116
+ @if map.get($utility, local-vars) {
117
+ @each $local-var-name, $local-var-value in map.get($utility, local-vars) {
118
+ --#{$local-var-name}: #{$local-var-value};
119
+ }
120
+ }
107
121
  }
108
122
  }
109
123
  }
@@ -25,6 +25,12 @@
25
25
  --#{config.$prefix}accordion-icon-color: #{accordion.$accordion-icon-color};
26
26
  --#{config.$prefix}accordion-icon-transform: #{accordion.$accordion-icon-transform};
27
27
  --#{config.$prefix}accordion-disable-color: #{accordion.$accordion-disable-color};
28
+ --#{config.$prefix}accordion-focus-border-color: #{accordion.$accordion-focus-border-color};
29
+ --#{config.$prefix}accordion-header-font-size: #{accordion.$accordion-header-font-size};
30
+ --#{config.$prefix}accordion-header-font-weight: #{accordion.$accordion-header-font-weight};
31
+ --#{config.$prefix}accordion-header-inner-gap: #{rem(accordion.$accordion-header-inner-gap)};
32
+ --#{config.$prefix}accordion-transition: #{accordion.$accordion-transition};
33
+ --#{config.$prefix}accordion-panel-transition: #{accordion.$accordion-panel-transition};
28
34
  --panel-height: 0px;
29
35
 
30
36
  width: 100%;
@@ -33,6 +39,7 @@
33
39
  var(--#{config.$prefix}accordion-border-color);
34
40
  border-radius: var(--#{config.$prefix}accordion-border-radius);
35
41
  overflow: hidden;
42
+ transition: var(--#{config.$prefix}accordion-transition);
36
43
 
37
44
  &__header {
38
45
  display: flex;
@@ -45,6 +52,9 @@
45
52
  border: none;
46
53
  outline: none;
47
54
  cursor: pointer;
55
+ font-size: var(--#{config.$prefix}accordion-header-font-size);
56
+ font-weight: var(--#{config.$prefix}accordion-header-font-weight);
57
+ gap: var(--#{config.$prefix}accordion-header-inner-gap);
48
58
  @include basic-transition(background);
49
59
 
50
60
  @include dynamic-background(var(--#{config.$prefix}accordion-header-bg));
@@ -52,22 +62,32 @@
52
62
  &--icon-left {
53
63
  flex-direction: row-reverse;
54
64
  justify-content: flex-end;
55
- gap: var(--#{config.$prefix}accordion-header-padding-x);
56
65
  }
57
66
 
58
67
  &:hover {
59
68
  --#{config.$prefix}accordion-header-bg: var(--#{config.$prefix}accordion-header-bg-hover);
60
69
  }
70
+
71
+ @if accordion.$accordion-enable-focus-ring {
72
+ &:focus-visible {
73
+ outline: 2px solid var(--#{config.$prefix}accordion-focus-border-color);
74
+ outline-offset: 2px;
75
+ }
76
+ }
61
77
  }
62
78
 
63
79
  &__title {
64
- margin-right: rem(20px);
80
+ flex: 1;
65
81
  }
66
82
 
67
83
  &__icon {
68
84
  color: var(--#{config.$prefix}accordion-icon-color);
69
85
  font-size: var(--#{config.$prefix}accordion-icon-size);
70
86
  will-change: transform;
87
+ flex-shrink: 0;
88
+ display: inline-flex;
89
+ align-items: center;
90
+ justify-content: center;
71
91
 
72
92
  @include basic-transition();
73
93
  }
@@ -77,6 +97,10 @@
77
97
  overflow: hidden;
78
98
  will-change: height;
79
99
 
100
+ @if accordion.$accordion-enable-smooth-scroll {
101
+ scroll-behavior: smooth;
102
+ }
103
+
80
104
  @include basic-transition();
81
105
  }
82
106
 
@@ -107,25 +131,43 @@
107
131
 
108
132
  &.is-disabled {
109
133
  pointer-events: none;
134
+ cursor: not-allowed;
110
135
 
111
136
  --#{config.$prefix}accordion-header-color: var(--#{config.$prefix}accordion-disable-color);
112
137
  --#{config.$prefix}accordion-body-color: var(--#{config.$prefix}accordion-disable-color);
113
138
  --#{config.$prefix}accordion-icon-color: var(--#{config.$prefix}accordion-disable-color);
114
- }
115
139
 
116
- &--glass {
117
- border-color: transparent;
118
140
  #{$root}__header {
119
- @include dynamic-background(
120
- var(--#{config.$prefix}accordion-header-bg),
121
- $background-transparency-enable: true
122
- );
141
+ cursor: not-allowed;
123
142
  }
124
- #{$root}__body {
125
- @include dynamic-background(
126
- var(--#{config.$prefix}accordion-header-bg),
127
- $background-transparency-enable: true
128
- );
143
+ }
144
+
145
+ @if accordion.$accordion-enable-glass {
146
+ &--glass {
147
+ border-color: transparent;
148
+ #{$root}__header {
149
+ @include dynamic-background(
150
+ var(--#{config.$prefix}accordion-header-bg),
151
+ $background-transparency-enable: true
152
+ );
153
+ }
154
+ #{$root}__body {
155
+ @include dynamic-background(
156
+ var(--#{config.$prefix}accordion-header-bg),
157
+ $background-transparency-enable: true
158
+ );
159
+ }
160
+ }
161
+ }
162
+
163
+ // Reduced motion support
164
+ @media (prefers-reduced-motion: reduce) {
165
+ transition: none;
166
+
167
+ #{$root}__icon,
168
+ #{$root}__panel,
169
+ #{$root}__header {
170
+ transition: none;
129
171
  }
130
172
  }
131
173
  }
@@ -26,6 +26,7 @@
26
26
  --#{$prefix}checkbox-border-color-hover: #{$checkbox-border-color-hover};
27
27
  --#{$prefix}checkbox-border-color-disabled: #{$checkbox-border-color-disabled};
28
28
  --#{$prefix}checkbox-border-color-error: #{$checkbox-border-color-error};
29
+ --#{$prefix}checkbox-checked-border-color: #{$checkbox-checked-bg};
29
30
 
30
31
  display: flex;
31
32
  gap: var(--#{$prefix}checkbox-spacer);
@@ -48,16 +49,22 @@
48
49
 
49
50
  &::before {
50
51
  position: absolute;
51
- top: -7px;
52
- left: -4px;
53
- font-family: 'Lux Icon';
54
- color: var(--#{$prefix}checkbox-checked-bg);
55
- content: '\ef10';
56
- font-size: rem(26px);
52
+ top: 0;
53
+ left: 0;
54
+ width: 100%;
55
+ height: 100%;
56
+ display: flex;
57
+ align-items: center;
58
+ justify-content: center;
59
+ color: var(--#{$prefix}checkbox-checked-text-color);
60
+ background: var(--#{$prefix}checkbox-checked-bg);
61
+ content: '';
57
62
  transform: scale(0);
58
- display: block;
59
- transform-origin: center;
60
- transition: 120ms transform ease-in-out;
63
+ opacity: 0;
64
+ transition: transform 120ms ease-in-out, opacity 120ms ease-in-out;
65
+ font-size: 0.65em;
66
+ line-height: 1;
67
+ font-family: 'Lux Icon';
61
68
  }
62
69
 
63
70
  &:hover {
@@ -65,23 +72,21 @@
65
72
  }
66
73
 
67
74
  &:checked {
68
- border-color: var(--#{$prefix}checkbox-checked-bg);
75
+ border-color: var(--#{$prefix}checkbox-checked-border-color);
69
76
 
70
77
  &::before {
78
+ content: '\ef10';
71
79
  transform: scale(1);
80
+ opacity: 1;
72
81
  }
73
82
 
74
83
  &:hover {
75
84
  border-color: var(--#{$prefix}checkbox-checked-bg-hover);
76
85
 
77
86
  &::before {
78
- color: var(--#{$prefix}checkbox-checked-bg-hover);
87
+ background: var(--#{$prefix}checkbox-checked-bg-hover);
79
88
  }
80
89
  }
81
-
82
- & + #{$root} {
83
- color: red;
84
- }
85
90
  }
86
91
 
87
92
  &:focus-visible {
@@ -93,7 +98,7 @@
93
98
  cursor: not-allowed;
94
99
 
95
100
  &::before {
96
- color: var(--#{$prefix}checkbox-checked-text-color-disabled) !important;
101
+ background: var(--#{$prefix}checkbox-checked-bg-disabled) !important;
97
102
  }
98
103
  }
99
104
  }
@@ -112,7 +117,7 @@
112
117
  cursor: not-allowed;
113
118
 
114
119
  &::before {
115
- color: var(--#{$prefix}checkbox-checked-text-color-disabled) !important;
120
+ background: var(--#{$prefix}checkbox-checked-bg-disabled) !important;
116
121
  }
117
122
  }
118
123
  }
@@ -130,6 +135,7 @@
130
135
  #{$root} {
131
136
  &__input::before {
132
137
  content: '\f0d6';
138
+ background: var(--#{$prefix}checkbox-checked-bg);
133
139
  }
134
140
  }
135
141
  }
@@ -5,6 +5,7 @@
5
5
  @forward 'utilities.display';
6
6
  @forward 'utilities.flex';
7
7
  @forward 'utilities.glass-fixes';
8
+ @forward 'utilities.gradient';
8
9
  @forward 'utilities.link';
9
10
  @forward 'utilities.object-fit';
10
11
  @forward 'utilities.opacity';
@@ -14,6 +15,7 @@
14
15
  @forward 'utilities.sizes';
15
16
  @forward 'utilities.spacing';
16
17
  @forward 'utilities.text';
18
+ @forward 'utilities.text-gradient';
17
19
  @forward 'utilities.visibility';
18
20
  @forward 'utilities.visually-hidden';
19
21
  @forward 'utilities.z-index';
@@ -19,6 +19,7 @@
19
19
  @use 'utilities.sizes' as sizes;
20
20
  @use 'utilities.spacing' as spacing;
21
21
  @use 'utilities.text' as text;
22
+ @use 'utilities.text-gradient' as textGradient;
22
23
  @use 'utilities.visibility' as visibility;
23
24
  @use 'utilities.z-index' as z-index;
24
25
 
@@ -40,6 +41,7 @@ $utilities: map.merge($utilities, spacing.$utilities-spacing);
40
41
  $utilities: map.merge($utilities, text.$utilities-text);
41
42
  $utilities: map.merge($utilities, visibility.$utilities-visibility);
42
43
  $utilities: map.merge($utilities, z-index.$utilities-z-index);
44
+ $utilities: map.merge($utilities, textGradient.$utilities-text-gradient);
43
45
 
44
46
  // Generate all utility classes
45
- @include util-api.generate-utilities($utilities, breakpoints.$grid-breakpoints);
47
+ @include util-api.generate-utilities($utilities, breakpoints.$grid-breakpoints);