@sankhyatronics/sankhya-cms 0.1.8 → 0.1.10

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 (116) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +34 -34
  3. package/custom-elements.json +1145 -1086
  4. package/dist/bento-grid/index.js +3 -3
  5. package/dist/card/index.js +2 -2
  6. package/dist/carousel/index.js +3 -3
  7. package/dist/{chunk-3JU3R22O.js → chunk-5EBWMPJS.js} +2 -2
  8. package/dist/chunk-5EBWMPJS.js.map +1 -0
  9. package/dist/{chunk-2JGWWXEI.js → chunk-76AVBQUA.js} +3 -3
  10. package/dist/chunk-76AVBQUA.js.map +1 -0
  11. package/dist/{chunk-NN3OCPDV.js → chunk-7NLZND6Q.js} +3 -3
  12. package/dist/{chunk-EMVHNAID.js → chunk-ALI26WOB.js} +3 -3
  13. package/dist/chunk-ALI26WOB.js.map +1 -0
  14. package/dist/{chunk-TLHG33MM.js → chunk-BLQV2YMO.js} +3 -3
  15. package/dist/chunk-BLQV2YMO.js.map +1 -0
  16. package/dist/{chunk-UVNBZD7R.js → chunk-BMHMNXIA.js} +3 -3
  17. package/dist/chunk-BMHMNXIA.js.map +1 -0
  18. package/dist/{chunk-ZRXYWH6C.js → chunk-DH53HZPB.js} +4 -4
  19. package/dist/{chunk-HPIQSECE.js → chunk-EMCQBT3S.js} +3 -3
  20. package/dist/{chunk-BQTDFQ4V.js → chunk-FLY7TNRT.js} +3 -3
  21. package/dist/chunk-FLY7TNRT.js.map +1 -0
  22. package/dist/{chunk-3VE6VFJ4.js → chunk-FZ36KL73.js} +1 -1
  23. package/dist/chunk-FZ36KL73.js.map +1 -0
  24. package/dist/{chunk-HGTC3LCW.js → chunk-G3CF7MBO.js} +3 -3
  25. package/dist/{chunk-CDC4P77V.js → chunk-GJO3RGOB.js} +2 -2
  26. package/dist/chunk-GJO3RGOB.js.map +1 -0
  27. package/dist/{chunk-K4ZICRZL.js → chunk-JKBWZLG4.js} +3 -3
  28. package/dist/chunk-JKBWZLG4.js.map +1 -0
  29. package/dist/{chunk-4HKSA5UT.js → chunk-JQY2G4QK.js} +2 -2
  30. package/dist/chunk-JQY2G4QK.js.map +1 -0
  31. package/dist/{chunk-RHAOQ6K4.js → chunk-KMU6ABQF.js} +1 -1
  32. package/dist/chunk-KMU6ABQF.js.map +1 -0
  33. package/dist/{chunk-IQPW3CYZ.js → chunk-LEXZKGQX.js} +3 -3
  34. package/dist/chunk-LEXZKGQX.js.map +1 -0
  35. package/dist/{chunk-MW43OS47.js → chunk-MSSH3HFK.js} +2 -2
  36. package/dist/chunk-MSSH3HFK.js.map +1 -0
  37. package/dist/{chunk-DQHMJZ6X.js → chunk-R5G6KFTJ.js} +18 -8
  38. package/dist/chunk-R5G6KFTJ.js.map +1 -0
  39. package/dist/{chunk-VYON56QO.js → chunk-SMLR736E.js} +2 -2
  40. package/dist/chunk-SMLR736E.js.map +1 -0
  41. package/dist/{chunk-HGJT24UG.js → chunk-VWS53WY4.js} +3 -3
  42. package/dist/chunk-VWS53WY4.js.map +1 -0
  43. package/dist/{chunk-VRRBMOUP.js → chunk-WT4OATGP.js} +3 -3
  44. package/dist/chunk-WT4OATGP.js.map +1 -0
  45. package/dist/{chunk-PB7ZPPLP.js → chunk-WTD2YIAA.js} +1 -1
  46. package/dist/chunk-WTD2YIAA.js.map +1 -0
  47. package/dist/{chunk-X2ALYIVT.js → chunk-XWB4CKDU.js} +20 -4
  48. package/dist/chunk-XWB4CKDU.js.map +1 -0
  49. package/dist/{chunk-XXPBFHWR.js → chunk-YQ42EBK5.js} +2 -2
  50. package/dist/chunk-YQ42EBK5.js.map +1 -0
  51. package/dist/{chunk-6H262SG6.js → chunk-YVTFQHVY.js} +2 -2
  52. package/dist/chunk-YVTFQHVY.js.map +1 -0
  53. package/dist/{chunk-7PSYCTEN.js → chunk-ZN4LIKVG.js} +2 -2
  54. package/dist/chunk-ZN4LIKVG.js.map +1 -0
  55. package/dist/cms-theme.css +26 -26
  56. package/dist/content-block/index.js +4 -4
  57. package/dist/cookie-consent/index.js +2 -2
  58. package/dist/dropdown/index.js +3 -3
  59. package/dist/feature-split/index.js +4 -4
  60. package/dist/features-section/index.js +5 -5
  61. package/dist/fonts/inter-latin-400-normal.woff2 +0 -0
  62. package/dist/fonts/inter-latin-500-normal.woff2 +0 -0
  63. package/dist/fonts/inter-latin-600-normal.woff2 +0 -0
  64. package/dist/fonts/inter-latin-700-normal.woff2 +0 -0
  65. package/dist/fonts.css +39 -0
  66. package/dist/footer/index.js +2 -2
  67. package/dist/header/index.d.ts +7 -0
  68. package/dist/header/index.js +3 -3
  69. package/dist/hero/index.js +3 -3
  70. package/dist/icon-button/index.js +2 -2
  71. package/dist/index.js +35 -35
  72. package/dist/items-accordion/index.js +3 -3
  73. package/dist/markdown/index.js +2 -2
  74. package/dist/mega-menu/index.js +3 -3
  75. package/dist/menu-grid/index.js +2 -2
  76. package/dist/menu-grid-item/index.js +2 -2
  77. package/dist/menu-item/index.d.ts +5 -0
  78. package/dist/menu-item/index.js +3 -3
  79. package/dist/promo-banner/index.js +3 -3
  80. package/dist/schema/index.js.map +1 -1
  81. package/dist/section/index.js +3 -3
  82. package/dist/select/index.js +3 -3
  83. package/dist/shared/icons.js +1 -1
  84. package/dist/shared/styles.js +1 -1
  85. package/dist/stats/index.js +2 -2
  86. package/dist/testimonials/index.js +4 -4
  87. package/dist/theme.css +340 -291
  88. package/dist/themes.css +84 -64
  89. package/dist/theming/index.js.map +1 -1
  90. package/package.json +4 -2
  91. package/dist/chunk-2JGWWXEI.js.map +0 -1
  92. package/dist/chunk-3JU3R22O.js.map +0 -1
  93. package/dist/chunk-3VE6VFJ4.js.map +0 -1
  94. package/dist/chunk-4HKSA5UT.js.map +0 -1
  95. package/dist/chunk-6H262SG6.js.map +0 -1
  96. package/dist/chunk-7PSYCTEN.js.map +0 -1
  97. package/dist/chunk-BQTDFQ4V.js.map +0 -1
  98. package/dist/chunk-CDC4P77V.js.map +0 -1
  99. package/dist/chunk-DQHMJZ6X.js.map +0 -1
  100. package/dist/chunk-EMVHNAID.js.map +0 -1
  101. package/dist/chunk-HGJT24UG.js.map +0 -1
  102. package/dist/chunk-IQPW3CYZ.js.map +0 -1
  103. package/dist/chunk-K4ZICRZL.js.map +0 -1
  104. package/dist/chunk-MW43OS47.js.map +0 -1
  105. package/dist/chunk-PB7ZPPLP.js.map +0 -1
  106. package/dist/chunk-RHAOQ6K4.js.map +0 -1
  107. package/dist/chunk-TLHG33MM.js.map +0 -1
  108. package/dist/chunk-UVNBZD7R.js.map +0 -1
  109. package/dist/chunk-VRRBMOUP.js.map +0 -1
  110. package/dist/chunk-VYON56QO.js.map +0 -1
  111. package/dist/chunk-X2ALYIVT.js.map +0 -1
  112. package/dist/chunk-XXPBFHWR.js.map +0 -1
  113. /package/dist/{chunk-NN3OCPDV.js.map → chunk-7NLZND6Q.js.map} +0 -0
  114. /package/dist/{chunk-ZRXYWH6C.js.map → chunk-DH53HZPB.js.map} +0 -0
  115. /package/dist/{chunk-HPIQSECE.js.map → chunk-EMCQBT3S.js.map} +0 -0
  116. /package/dist/{chunk-HGTC3LCW.js.map → chunk-G3CF7MBO.js.map} +0 -0
package/dist/themes.css CHANGED
@@ -1,65 +1,85 @@
1
- :root.dark {
2
- --st-primary-color: oklch(97.913% 0.00011 271.152);
3
- --st-primary-background: oklch(11.862% 0.03663 260.411 / 0.808);
4
- --st-font-family: "Open Sans";
5
- }
6
-
7
- :root.red {
8
- --st-primary-color: oklch(25.8% 0.092 26.042);
9
- --st-primary-background: oklch(97.1% 0.013 17.38);
10
- --st-font-family: 'Arimo';
11
- }
12
-
13
- :root.amber {
14
- --st-primary-color: oklch(27.9% 0.077 45.635);
15
- --st-primary-background: oklch(98.7% 0.022 95.277);
16
- --st-font-family: "Open Sans";
17
- }
18
-
19
- :root.lime {
20
- --st-primary-color: oklch(27.4% 0.072 132.109);
21
- --st-primary-background: oklch(98.6% 0.031 120.757);
22
- --st-font-family: "Quicksand";
23
- }
24
-
25
- :root.teal {
26
- --st-primary-color: oklch(27.7% 0.046 192.524);
27
- --st-primary-background: oklch(98.4% 0.014 180.72);
28
- --st-font-family: "Nunito";
29
- }
30
-
31
- :root.cyan {
32
- --st-primary-color: oklch(30.2% 0.056 229.695);
33
- --st-primary-background: oklch(98.4% 0.019 200.873);
34
- --st-font-family: "Arimo";
35
- }
36
-
37
- :root.sky {
38
- --st-primary-color: oklch(29.3% 0.066 243.157);
39
- --st-primary-background: oklch(97.7% 0.013 236.62);
40
- --st-font-family: "Almendra";
41
- }
42
-
43
- :root.blue {
44
- --st-primary-color: oklch(28.2% 0.091 267.935);
45
- --st-primary-background: oklch(97% 0.014 254.604);
46
- --st-font-family: "Miranda Sans";
47
- }
48
-
49
- :root.indigo {
50
- --st-primary-color: oklch(25.7% 0.09 281.288);
51
- --st-primary-background: oklch(96.2% 0.018 272.314);
52
- --st-font-family: "Nunito";
53
- }
54
-
55
- :root.fuchsia {
56
- --st-primary-color: oklch(29.3% 0.136 325.661);
57
- --st-primary-background: oklch(97.7% 0.017 320.058);
58
- --st-font-family: "Quicksand";
59
- }
60
-
61
- :root.pink {
62
- --st-primary-color: oklch(28.4% 0.109 3.907);
63
- --st-primary-background: oklch(97.1% 0.014 343.198);
64
- --st-font-family: "Open Sans";
1
+ :root.dark {
2
+ --st-primary-color: oklch(97.913% 0.00011 271.152);
3
+ --st-primary-background: oklch(11.862% 0.03663 260.411 / 0.808);
4
+ --st-font-family: "Open Sans";
5
+
6
+ /* The light-theme literals in theme.css, re-set for dark. Not part of the
7
+ light design spec: these keep every surface, line and status readable. */
8
+ --st-primary-canvas: #1B1F2B;
9
+ --st-primary-accent: var(--st-brand-color, #6F8BFF);
10
+ --st-primary-line: #2A3142;
11
+ --st-primary-divider: #232937;
12
+ --st-primary-text-secondary: #B9C0CE;
13
+ --st-primary-text-muted: #9AA2B5;
14
+ --st-primary-brand-soft: #1E2A4F;
15
+ --st-primary-brand-ink: #AFC3FF;
16
+ --st-primary-success: #2FB97F;
17
+ --st-primary-warning: #E0893A;
18
+ --st-primary-danger: #E0576B;
19
+ --st-primary-success-soft: #123329;
20
+ --st-primary-warning-soft: #3A2A12;
21
+ --st-primary-danger-soft: #3B1A22;
22
+ --st-primary-success-text: #6EDCA9;
23
+ --st-primary-warning-text: #F5C27A;
24
+ --st-primary-danger-text: #FF9AA8;
25
+ }
26
+
27
+ :root.red {
28
+ --st-primary-color: oklch(25.8% 0.092 26.042);
29
+ --st-primary-background: oklch(97.1% 0.013 17.38);
30
+ --st-font-family: 'Arimo';
31
+ }
32
+
33
+ :root.amber {
34
+ --st-primary-color: oklch(27.9% 0.077 45.635);
35
+ --st-primary-background: oklch(98.7% 0.022 95.277);
36
+ --st-font-family: "Open Sans";
37
+ }
38
+
39
+ :root.lime {
40
+ --st-primary-color: oklch(27.4% 0.072 132.109);
41
+ --st-primary-background: oklch(98.6% 0.031 120.757);
42
+ --st-font-family: "Quicksand";
43
+ }
44
+
45
+ :root.teal {
46
+ --st-primary-color: oklch(27.7% 0.046 192.524);
47
+ --st-primary-background: oklch(98.4% 0.014 180.72);
48
+ --st-font-family: "Nunito";
49
+ }
50
+
51
+ :root.cyan {
52
+ --st-primary-color: oklch(30.2% 0.056 229.695);
53
+ --st-primary-background: oklch(98.4% 0.019 200.873);
54
+ --st-font-family: "Arimo";
55
+ }
56
+
57
+ :root.sky {
58
+ --st-primary-color: oklch(29.3% 0.066 243.157);
59
+ --st-primary-background: oklch(97.7% 0.013 236.62);
60
+ --st-font-family: "Almendra";
61
+ }
62
+
63
+ :root.blue {
64
+ --st-primary-color: oklch(28.2% 0.091 267.935);
65
+ --st-primary-background: oklch(97% 0.014 254.604);
66
+ --st-font-family: "Miranda Sans";
67
+ }
68
+
69
+ :root.indigo {
70
+ --st-primary-color: oklch(25.7% 0.09 281.288);
71
+ --st-primary-background: oklch(96.2% 0.018 272.314);
72
+ --st-font-family: "Nunito";
73
+ }
74
+
75
+ :root.fuchsia {
76
+ --st-primary-color: oklch(29.3% 0.136 325.661);
77
+ --st-primary-background: oklch(97.7% 0.017 320.058);
78
+ --st-font-family: "Quicksand";
79
+ }
80
+
81
+ :root.pink {
82
+ --st-primary-color: oklch(28.4% 0.109 3.907);
83
+ --st-primary-background: oklch(97.1% 0.014 343.198);
84
+ --st-font-family: "Open Sans";
65
85
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/theming/index.ts"],"sourcesContent":["/**\r\n * Theme runtime for `themes.css`: the list of themes, and applying one to `<html>`.\r\n * Framework-free and storage-free — where the chosen theme is remembered is up to the host app.\r\n */\r\n\r\nexport interface ThemeOption {\r\n value: string;\r\n label: string;\r\n /** Approximate color for a picker swatch, not the palette itself (that's `themes.css`). */\r\n swatch: string;\r\n dark: boolean;\r\n}\r\n\r\nexport const DEFAULT_THEME = 'default';\r\n\r\n/** `'default'` applies no class (the base palette); every other value is a class in `themes.css`. */\r\nexport const THEMES: readonly ThemeOption[] = [\r\n { value: 'default', label: 'Default', swatch: '#94a3b8', dark: false },\r\n { value: 'dark', label: 'Dark', swatch: '#1f2937', dark: true },\r\n { value: 'red', label: 'Red', swatch: '#ef4444', dark: false },\r\n { value: 'amber', label: 'Amber', swatch: '#f59e0b', dark: false },\r\n { value: 'lime', label: 'Lime', swatch: '#84cc16', dark: false },\r\n { value: 'teal', label: 'Teal', swatch: '#14b8a6', dark: false },\r\n { value: 'cyan', label: 'Cyan', swatch: '#06b6d4', dark: false },\r\n { value: 'sky', label: 'Sky', swatch: '#0ea5e9', dark: false },\r\n { value: 'blue', label: 'Blue', swatch: '#3b82f6', dark: false },\r\n { value: 'indigo', label: 'Indigo', swatch: '#6366f1', dark: false },\r\n { value: 'fuchsia', label: 'Fuchsia', swatch: '#d946ef', dark: false },\r\n { value: 'pink', label: 'Pink', swatch: '#ec4899', dark: false }\r\n];\r\n\r\nexport function isTheme(value: unknown): value is string {\r\n return typeof value === 'string' && THEMES.some(theme => theme.value === value);\r\n}\r\n\r\nconst THEME_CLASSES = THEMES.filter(theme => theme.value !== DEFAULT_THEME).map(theme => theme.value);\r\nconst DARK_QUERY = '(prefers-color-scheme: dark)';\r\n\r\n/** The theme to use when nobody has chosen one: `dark` if the OS prefers it, else `default`. */\r\nexport function systemTheme(): string {\r\n if (typeof window === 'undefined' || !window.matchMedia) return DEFAULT_THEME;\r\n return window.matchMedia(DARK_QUERY).matches ? 'dark' : DEFAULT_THEME;\r\n}\r\n\r\n/** Calls `onChange` when the OS light/dark setting flips; returns an unsubscribe function. */\r\nexport function watchSystemTheme(onChange: (theme: string) => void): () => void {\r\n if (typeof window === 'undefined' || !window.matchMedia) return () => {};\r\n const query = window.matchMedia(DARK_QUERY);\r\n const listener = () => onChange(systemTheme());\r\n query.addEventListener('change', listener);\r\n return () => query.removeEventListener('change', listener);\r\n}\r\n\r\n/**\r\n * Applies a theme to `<html>`: swaps only the theme classes (other classes on the element are left\r\n * alone) and sets `color-scheme` so native controls and scrollbars match. `null`/`undefined` means\r\n * \"nobody chose\", which follows the OS; an unknown value falls back to `default`. Returns the\r\n * theme actually applied.\r\n */\r\nexport function applyTheme(theme: string | null | undefined): string {\r\n const resolved = theme === null || theme === undefined ? systemTheme() : isTheme(theme) ? theme : DEFAULT_THEME;\r\n if (typeof document === 'undefined') return resolved;\r\n const root = document.documentElement;\r\n root.classList.remove(...THEME_CLASSES);\r\n if (resolved !== DEFAULT_THEME) root.classList.add(resolved);\r\n root.style.colorScheme = THEMES.find(option => option.value === resolved)?.dark ? 'dark' : 'light';\r\n return resolved;\r\n}\r\n"],"mappings":";;;AAaO,IAAM,gBAAgB;AAGtB,IAAM,SAAiC;AAAA,EAC5C,EAAE,OAAO,WAAW,OAAO,WAAW,QAAQ,WAAW,MAAM,MAAM;AAAA,EACrE,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,WAAW,MAAM,KAAK;AAAA,EAC9D,EAAE,OAAO,OAAO,OAAO,OAAO,QAAQ,WAAW,MAAM,MAAM;AAAA,EAC7D,EAAE,OAAO,SAAS,OAAO,SAAS,QAAQ,WAAW,MAAM,MAAM;AAAA,EACjE,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,WAAW,MAAM,MAAM;AAAA,EAC/D,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,WAAW,MAAM,MAAM;AAAA,EAC/D,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,WAAW,MAAM,MAAM;AAAA,EAC/D,EAAE,OAAO,OAAO,OAAO,OAAO,QAAQ,WAAW,MAAM,MAAM;AAAA,EAC7D,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,WAAW,MAAM,MAAM;AAAA,EAC/D,EAAE,OAAO,UAAU,OAAO,UAAU,QAAQ,WAAW,MAAM,MAAM;AAAA,EACnE,EAAE,OAAO,WAAW,OAAO,WAAW,QAAQ,WAAW,MAAM,MAAM;AAAA,EACrE,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,WAAW,MAAM,MAAM;AACjE;AAEO,SAAS,QAAQ,OAAiC;AACvD,SAAO,OAAO,UAAU,YAAY,OAAO,KAAK,WAAS,MAAM,UAAU,KAAK;AAChF;AAEA,IAAM,gBAAgB,OAAO,OAAO,WAAS,MAAM,UAAU,aAAa,EAAE,IAAI,WAAS,MAAM,KAAK;AACpG,IAAM,aAAa;AAGZ,SAAS,cAAsB;AACpC,MAAI,OAAO,WAAW,eAAe,CAAC,OAAO,WAAY,QAAO;AAChE,SAAO,OAAO,WAAW,UAAU,EAAE,UAAU,SAAS;AAC1D;AAGO,SAAS,iBAAiB,UAA+C;AAC9E,MAAI,OAAO,WAAW,eAAe,CAAC,OAAO,WAAY,QAAO,MAAM;AAAA,EAAC;AACvE,QAAM,QAAQ,OAAO,WAAW,UAAU;AAC1C,QAAM,WAAW,MAAM,SAAS,YAAY,CAAC;AAC7C,QAAM,iBAAiB,UAAU,QAAQ;AACzC,SAAO,MAAM,MAAM,oBAAoB,UAAU,QAAQ;AAC3D;AAQO,SAAS,WAAW,OAA0C;AACnE,QAAM,WAAW,UAAU,QAAQ,UAAU,SAAY,YAAY,IAAI,QAAQ,KAAK,IAAI,QAAQ;AAClG,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,QAAM,OAAO,SAAS;AACtB,OAAK,UAAU,OAAO,GAAG,aAAa;AACtC,MAAI,aAAa,cAAe,MAAK,UAAU,IAAI,QAAQ;AAC3D,OAAK,MAAM,cAAc,OAAO,KAAK,YAAU,OAAO,UAAU,QAAQ,GAAG,OAAO,SAAS;AAC3F,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/theming/index.ts"],"sourcesContent":["/**\n * Theme runtime for `themes.css`: the list of themes, and applying one to `<html>`.\n * Framework-free and storage-free — where the chosen theme is remembered is up to the host app.\n */\n\nexport interface ThemeOption {\n value: string;\n label: string;\n /** Approximate color for a picker swatch, not the palette itself (that's `themes.css`). */\n swatch: string;\n dark: boolean;\n}\n\nexport const DEFAULT_THEME = 'default';\n\n/** `'default'` applies no class (the base palette); every other value is a class in `themes.css`. */\nexport const THEMES: readonly ThemeOption[] = [\n { value: 'default', label: 'Default', swatch: '#94a3b8', dark: false },\n { value: 'dark', label: 'Dark', swatch: '#1f2937', dark: true },\n { value: 'red', label: 'Red', swatch: '#ef4444', dark: false },\n { value: 'amber', label: 'Amber', swatch: '#f59e0b', dark: false },\n { value: 'lime', label: 'Lime', swatch: '#84cc16', dark: false },\n { value: 'teal', label: 'Teal', swatch: '#14b8a6', dark: false },\n { value: 'cyan', label: 'Cyan', swatch: '#06b6d4', dark: false },\n { value: 'sky', label: 'Sky', swatch: '#0ea5e9', dark: false },\n { value: 'blue', label: 'Blue', swatch: '#3b82f6', dark: false },\n { value: 'indigo', label: 'Indigo', swatch: '#6366f1', dark: false },\n { value: 'fuchsia', label: 'Fuchsia', swatch: '#d946ef', dark: false },\n { value: 'pink', label: 'Pink', swatch: '#ec4899', dark: false }\n];\n\nexport function isTheme(value: unknown): value is string {\n return typeof value === 'string' && THEMES.some(theme => theme.value === value);\n}\n\nconst THEME_CLASSES = THEMES.filter(theme => theme.value !== DEFAULT_THEME).map(theme => theme.value);\nconst DARK_QUERY = '(prefers-color-scheme: dark)';\n\n/** The theme to use when nobody has chosen one: `dark` if the OS prefers it, else `default`. */\nexport function systemTheme(): string {\n if (typeof window === 'undefined' || !window.matchMedia) return DEFAULT_THEME;\n return window.matchMedia(DARK_QUERY).matches ? 'dark' : DEFAULT_THEME;\n}\n\n/** Calls `onChange` when the OS light/dark setting flips; returns an unsubscribe function. */\nexport function watchSystemTheme(onChange: (theme: string) => void): () => void {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {};\n const query = window.matchMedia(DARK_QUERY);\n const listener = () => onChange(systemTheme());\n query.addEventListener('change', listener);\n return () => query.removeEventListener('change', listener);\n}\n\n/**\n * Applies a theme to `<html>`: swaps only the theme classes (other classes on the element are left\n * alone) and sets `color-scheme` so native controls and scrollbars match. `null`/`undefined` means\n * \"nobody chose\", which follows the OS; an unknown value falls back to `default`. Returns the\n * theme actually applied.\n */\nexport function applyTheme(theme: string | null | undefined): string {\n const resolved = theme === null || theme === undefined ? systemTheme() : isTheme(theme) ? theme : DEFAULT_THEME;\n if (typeof document === 'undefined') return resolved;\n const root = document.documentElement;\n root.classList.remove(...THEME_CLASSES);\n if (resolved !== DEFAULT_THEME) root.classList.add(resolved);\n root.style.colorScheme = THEMES.find(option => option.value === resolved)?.dark ? 'dark' : 'light';\n return resolved;\n}\n"],"mappings":";;;AAaO,IAAM,gBAAgB;AAGtB,IAAM,SAAiC;AAAA,EAC5C,EAAE,OAAO,WAAW,OAAO,WAAW,QAAQ,WAAW,MAAM,MAAM;AAAA,EACrE,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,WAAW,MAAM,KAAK;AAAA,EAC9D,EAAE,OAAO,OAAO,OAAO,OAAO,QAAQ,WAAW,MAAM,MAAM;AAAA,EAC7D,EAAE,OAAO,SAAS,OAAO,SAAS,QAAQ,WAAW,MAAM,MAAM;AAAA,EACjE,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,WAAW,MAAM,MAAM;AAAA,EAC/D,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,WAAW,MAAM,MAAM;AAAA,EAC/D,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,WAAW,MAAM,MAAM;AAAA,EAC/D,EAAE,OAAO,OAAO,OAAO,OAAO,QAAQ,WAAW,MAAM,MAAM;AAAA,EAC7D,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,WAAW,MAAM,MAAM;AAAA,EAC/D,EAAE,OAAO,UAAU,OAAO,UAAU,QAAQ,WAAW,MAAM,MAAM;AAAA,EACnE,EAAE,OAAO,WAAW,OAAO,WAAW,QAAQ,WAAW,MAAM,MAAM;AAAA,EACrE,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,WAAW,MAAM,MAAM;AACjE;AAEO,SAAS,QAAQ,OAAiC;AACvD,SAAO,OAAO,UAAU,YAAY,OAAO,KAAK,WAAS,MAAM,UAAU,KAAK;AAChF;AAEA,IAAM,gBAAgB,OAAO,OAAO,WAAS,MAAM,UAAU,aAAa,EAAE,IAAI,WAAS,MAAM,KAAK;AACpG,IAAM,aAAa;AAGZ,SAAS,cAAsB;AACpC,MAAI,OAAO,WAAW,eAAe,CAAC,OAAO,WAAY,QAAO;AAChE,SAAO,OAAO,WAAW,UAAU,EAAE,UAAU,SAAS;AAC1D;AAGO,SAAS,iBAAiB,UAA+C;AAC9E,MAAI,OAAO,WAAW,eAAe,CAAC,OAAO,WAAY,QAAO,MAAM;AAAA,EAAC;AACvE,QAAM,QAAQ,OAAO,WAAW,UAAU;AAC1C,QAAM,WAAW,MAAM,SAAS,YAAY,CAAC;AAC7C,QAAM,iBAAiB,UAAU,QAAQ;AACzC,SAAO,MAAM,MAAM,oBAAoB,UAAU,QAAQ;AAC3D;AAQO,SAAS,WAAW,OAA0C;AACnE,QAAM,WAAW,UAAU,QAAQ,UAAU,SAAY,YAAY,IAAI,QAAQ,KAAK,IAAI,QAAQ;AAClG,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,QAAM,OAAO,SAAS;AACtB,OAAK,UAAU,OAAO,GAAG,aAAa;AACtC,MAAI,aAAa,cAAe,MAAK,UAAU,IAAI,QAAQ;AAC3D,OAAK,MAAM,cAAc,OAAO,KAAK,YAAU,OAAO,UAAU,QAAQ,GAAG,OAAO,SAAS;AAC3F,SAAO;AACT;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sankhyatronics/sankhya-cms",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sankhyatronics/SankhyaCMS.git",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "./cms-theme.css": "./dist/cms-theme.css",
20
20
  "./theme.css": "./dist/theme.css",
21
+ "./fonts.css": "./dist/fonts.css",
21
22
  "./themes.css": "./dist/themes.css",
22
23
  "./bento-grid": {
23
24
  "types": "./dist/bento-grid/index.d.ts",
@@ -135,6 +136,7 @@
135
136
  ],
136
137
  "sideEffects": true,
137
138
  "dependencies": {
139
+ "@fontsource/inter": "^5.3.0",
138
140
  "dompurify": "^3.4.16",
139
141
  "iconify-icon": "^3.0.3",
140
142
  "lit": "^3.3.3",
@@ -151,7 +153,7 @@
151
153
  "access": "public"
152
154
  },
153
155
  "scripts": {
154
- "build": "tsup src/index.ts src/schema/index.ts src/theming/index.ts src/shared/styles.ts src/shared/icons.ts src/bento-grid/index.ts src/card/index.ts src/carousel/index.ts src/content-block/index.ts src/cookie-consent/index.ts src/dropdown/index.ts src/feature-split/index.ts src/features-section/index.ts src/footer/index.ts src/header/index.ts src/hero/index.ts src/icon-button/index.ts src/items-accordion/index.ts src/markdown/index.ts src/mega-menu/index.ts src/menu-grid/index.ts src/menu-grid-item/index.ts src/menu-item/index.ts src/promo-banner/index.ts src/section/index.ts src/select/index.ts src/stats/index.ts src/testimonials/index.ts --format esm --dts --sourcemap --clean && node scripts/copy-theme.mjs && cem analyze",
156
+ "build": "tsup src/index.ts src/schema/index.ts src/theming/index.ts src/shared/styles.ts src/shared/icons.ts src/bento-grid/index.ts src/card/index.ts src/carousel/index.ts src/content-block/index.ts src/cookie-consent/index.ts src/dropdown/index.ts src/feature-split/index.ts src/features-section/index.ts src/footer/index.ts src/header/index.ts src/hero/index.ts src/icon-button/index.ts src/items-accordion/index.ts src/markdown/index.ts src/mega-menu/index.ts src/menu-grid/index.ts src/menu-grid-item/index.ts src/menu-item/index.ts src/promo-banner/index.ts src/section/index.ts src/select/index.ts src/stats/index.ts src/testimonials/index.ts --format esm --dts --sourcemap --clean && node scripts/copy-theme.mjs && node scripts/copy-fonts.mjs && cem analyze",
155
157
  "dev": "tsup src/index.ts --watch --format esm --dts",
156
158
  "typecheck": "tsc --noEmit",
157
159
  "lint": "oxlint",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/bento-grid/BentoGrid.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\nimport 'iconify-icon';\r\n\r\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport {\r\n cardTitleStyles,\r\n iconTileStyles,\r\n reducedMotionStyles,\r\n sectionHeaderStyles,\r\n sectionSubtitleStyles,\r\n sectionTitleStyles, invertedSectionTextStyles } from '../shared/section-styles';\r\n\r\nexport interface BentoGridItem {\r\n title: string;\r\n description?: string;\r\n /** Iconify icon name, e.g. `mdi:home`. */\r\n icon?: string;\r\n imageSrc?: string;\r\n imageAlt?: string;\r\n colSpan?: 1 | 2 | 3 | 4;\r\n rowSpan?: 1 | 2;\r\n /** Turns the card into a link. */\r\n href?: string;\r\n}\r\n\r\n/**\r\n * A responsive 4-column bento grid of icon/image cards. Items are set via the `items` property.\r\n *\r\n * @cssprop --st-bento-grid-padding - Overrides the block's padding.\r\n */\r\n@customElement('st-bento-grid')\r\nexport class BentoGrid extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n /* !important: a page-level reset (e.g. Tailwind Preflight) otherwise zeroes a shadow host's\r\n padding; override with --st-bento-grid-padding instead. */\r\n padding: var(--st-bento-grid-padding, var(--st-cms-section-padding) var(--st-space-24)) !important;\r\n background: var(--st-color-page);\r\n ${fontFamilyStyles}\r\n }\r\n\r\n :host([inverted]) {\r\n background: var(--st-color-text-strong);\r\n }\r\n\r\n .container {\r\n max-width: var(--st-cms-container-max);\r\n margin: 0 auto;\r\n }\r\n\r\n .header {\r\n ${sectionHeaderStyles}\r\n }\r\n\r\n .title {\r\n ${sectionTitleStyles}\r\n }\r\n\r\n .subtitle {\r\n ${sectionSubtitleStyles}\r\n margin-bottom: 0;\r\n }\r\n\r\n ${invertedSectionTextStyles}\r\n\r\n .grid {\r\n display: grid;\r\n grid-template-columns: repeat(4, 1fr);\r\n grid-auto-rows: minmax(240px, auto);\r\n gap: var(--st-space-24);\r\n }\r\n\r\n .card {\r\n position: relative;\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n border: 1px solid var(--st-color-border);\r\n border-radius: var(--st-space-24);\r\n background: var(--st-color-surface);\r\n color: inherit;\r\n text-decoration: none;\r\n transition:\r\n transform 0.3s ease,\r\n box-shadow 0.3s ease;\r\n }\r\n\r\n :host([inverted]) .card {\r\n background: var(--st-color-text-strong);\r\n border-color: var(--st-color-text);\r\n }\r\n\r\n .card:hover {\r\n transform: translateY(-4px);\r\n box-shadow: 0 12px 24px -10px var(--st-shadow-color-lg);\r\n z-index: 1;\r\n }\r\n\r\n .image-wrapper {\r\n position: absolute;\r\n inset: 0;\r\n }\r\n\r\n .image-wrapper::after {\r\n content: '';\r\n position: absolute;\r\n inset: 0;\r\n background: linear-gradient(to bottom, transparent 0%, var(--st-shadow-color-xl) 100%);\r\n }\r\n\r\n .image {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n transition: transform 0.5s ease;\r\n }\r\n\r\n .card:hover .image {\r\n transform: scale(1.05);\r\n }\r\n\r\n .content {\r\n position: relative;\r\n z-index: 1;\r\n margin-top: auto;\r\n padding: var(--st-space-24);\r\n display: flex;\r\n flex-direction: column;\r\n gap: var(--st-space-16);\r\n }\r\n\r\n .icon {\r\n ${iconTileStyles}\r\n width: var(--st-size-40);\r\n height: var(--st-size-40);\r\n font-size: 24px;\r\n }\r\n\r\n .text {\r\n padding: var(--st-space-16);\r\n border-radius: var(--st-radius-md);\r\n }\r\n\r\n .card-title {\r\n ${cardTitleStyles}\r\n font-size: var(--st-text-lg);\r\n }\r\n\r\n .card-description {\r\n margin: 0;\r\n font-size: var(--st-text-md);\r\n color: var(--st-color-text-muted);\r\n }\r\n\r\n :host([inverted]) .card-title {\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n :host([inverted]) .card-description {\r\n color: var(--st-color-border);\r\n }\r\n\r\n .card.has-image .card-title,\r\n .card.has-image .card-description {\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n .card.has-image .icon {\r\n background: var(--st-shadow-color-lg);\r\n color: var(--st-color-on-solid);\r\n backdrop-filter: blur(4px);\r\n }\r\n\r\n .col-1 { grid-column: span 1; }\r\n .col-2 { grid-column: span 2; }\r\n .col-3 { grid-column: span 3; }\r\n .col-4 { grid-column: span 4; }\r\n .row-1 { grid-row: span 1; }\r\n .row-2 { grid-row: span 2; }\r\n\r\n @media (max-width: 1024px) {\r\n .grid {\r\n grid-template-columns: repeat(2, 1fr);\r\n }\r\n .col-3,\r\n .col-4 {\r\n grid-column: span 2;\r\n }\r\n }\r\n\r\n @media (max-width: 640px) {\r\n .grid {\r\n grid-template-columns: 1fr;\r\n }\r\n .col-1,\r\n .col-2,\r\n .col-3,\r\n .col-4 {\r\n grid-column: span 1;\r\n }\r\n }\r\n\r\n ${reducedMotionStyles}\r\n `;\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n @property({ type: String })\r\n subtitle = '';\r\n\r\n @property({ attribute: false })\r\n items: BentoGridItem[] = [];\r\n\r\n private renderCard(item: BentoGridItem) {\r\n const classes = `card col-${item.colSpan ?? 1} row-${item.rowSpan ?? 1} ${item.imageSrc ? 'has-image' : ''}`;\r\n const body = html`\r\n ${item.imageSrc\r\n ? html`<div class=\"image-wrapper\" part=\"image-wrapper\">\r\n <img class=\"image\" part=\"image\" src=${item.imageSrc} alt=${item.imageAlt ?? item.title} />\r\n </div>`\r\n : nothing}\r\n <div class=\"content\" part=\"content\">\r\n ${item.icon ? html`<div class=\"icon\" part=\"icon\"><iconify-icon icon=${item.icon}></iconify-icon></div>` : nothing}\r\n <div class=\"text\">\r\n <h3 class=\"card-title\" part=\"card-title\">${item.title}</h3>\r\n ${item.description ? html`<p class=\"card-description\" part=\"card-description\">${item.description}</p>` : nothing}\r\n </div>\r\n </div>\r\n `;\r\n return item.href\r\n ? html`<a part=\"card\" class=${classes} href=${item.href}>${body}</a>`\r\n : html`<div part=\"card\" class=${classes}>${body}</div>`;\r\n }\r\n\r\n render() {\r\n return html`\r\n <div class=\"container\" part=\"container\">\r\n ${this.title || this.subtitle\r\n ? html`<div class=\"header\" part=\"header\">\r\n ${this.title ? html`<h2 class=\"title\" part=\"title\">${this.title}</h2>` : nothing}\r\n ${this.subtitle ? html`<p class=\"subtitle\" part=\"subtitle\">${this.subtitle}</p>` : nothing}\r\n </div>`\r\n : nothing}\r\n <div class=\"grid\" part=\"grid\">${this.items.map((item) => this.renderCard(item))}</div>\r\n </div>\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/markdown/Markdown.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property, state } from 'lit/decorators.js';\r\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js';\r\nimport DOMPurify from 'dompurify';\r\nimport { marked } from 'marked';\r\n\r\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport type { MarkdownErrorEventDetail } from './MarkdownEvents';\r\n\r\n/**\r\n * Renders Markdown (GFM, single newlines become `<br>`) from either an inline `content` string or\r\n * a `src` URL it fetches. Ports `SankhyaUI`'s `useMarkdown` hook + `react-markdown` (remark-gfm,\r\n * remark-breaks); output is sanitized with DOMPurify. `src` wins over `content` when both are set.\r\n * While a fetch is pending it shows \"Loading content...\"; on failure \"Error loading content.\" and\r\n * a `markdown-error` event (detail: `{ error }`).\r\n *\r\n * Text color is inherited from the parent so inverted containers just work.\r\n */\r\n@customElement('st-markdown')\r\nexport class Markdown extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n ${fontFamilyStyles}\r\n line-height: 1.7;\r\n }\r\n\r\n :host > div > :first-child {\r\n margin-top: 0;\r\n }\r\n\r\n h1,\r\n h2,\r\n h3,\r\n h4 {\r\n color: inherit;\r\n font-weight: var(--st-font-weight-bold);\r\n line-height: 1.3;\r\n }\r\n\r\n h2 {\r\n font-size: var(--st-text-2xl);\r\n margin: var(--st-space-48) 0 var(--st-space-24);\r\n }\r\n\r\n h3 {\r\n font-size: var(--st-text-xl);\r\n font-weight: var(--st-font-weight-semibold);\r\n margin: var(--st-space-32) 0 var(--st-space-16);\r\n }\r\n\r\n p {\r\n margin: 0 0 var(--st-space-24);\r\n }\r\n\r\n ul,\r\n ol {\r\n margin: 0 0 var(--st-space-24);\r\n padding-left: var(--st-space-24);\r\n }\r\n\r\n li {\r\n margin-bottom: var(--st-space-8);\r\n }\r\n\r\n a {\r\n color: inherit;\r\n text-decoration: underline;\r\n text-underline-offset: 4px;\r\n }\r\n\r\n a:hover {\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n img {\r\n max-width: 100%;\r\n height: auto;\r\n border-radius: var(--st-radius-sm);\r\n margin: var(--st-space-32) 0;\r\n }\r\n\r\n blockquote {\r\n border-left: 4px solid var(--st-color-border);\r\n margin: var(--st-space-32) 0;\r\n padding-left: var(--st-space-24);\r\n font-style: italic;\r\n }\r\n\r\n table {\r\n border-collapse: collapse;\r\n margin: 0 0 var(--st-space-24);\r\n }\r\n\r\n th,\r\n td {\r\n border: 1px solid var(--st-color-border);\r\n padding: var(--st-space-8) var(--st-space-12);\r\n }\r\n\r\n pre,\r\n code {\r\n background: var(--st-color-subtle);\r\n border-radius: var(--st-radius-xs);\r\n }\r\n\r\n code {\r\n padding: 0 var(--st-space-4);\r\n }\r\n\r\n pre {\r\n padding: var(--st-space-16);\r\n overflow-x: auto;\r\n }\r\n\r\n pre code {\r\n padding: 0;\r\n }\r\n `;\r\n\r\n /** Inline Markdown source. Ignored when `src` is set. */\r\n @property({ type: String })\r\n content = '';\r\n\r\n /** URL of a Markdown file to fetch. */\r\n @property({ type: String })\r\n src = '';\r\n\r\n @state() private fetched = '';\r\n @state() private loading = false;\r\n @state() private error: Error | null = null;\r\n\r\n private abort?: AbortController;\r\n\r\n willUpdate(changed: Map<string, unknown>): void {\r\n if (changed.has('src')) void this.load();\r\n }\r\n\r\n disconnectedCallback(): void {\r\n this.abort?.abort();\r\n super.disconnectedCallback();\r\n }\r\n\r\n private async load(): Promise<void> {\r\n this.abort?.abort();\r\n this.fetched = '';\r\n this.error = null;\r\n if (!this.src) {\r\n this.loading = false;\r\n return;\r\n }\r\n const controller = new AbortController();\r\n this.abort = controller;\r\n this.loading = true;\r\n try {\r\n const response = await fetch(this.src, { signal: controller.signal });\r\n if (!response.ok) throw new Error(`Failed to fetch markdown: ${response.statusText}`);\r\n const text = await response.text();\r\n if (controller.signal.aborted) return;\r\n this.fetched = text;\r\n } catch (err) {\r\n if (controller.signal.aborted) return;\r\n this.error = err instanceof Error ? err : new Error('Unknown error fetching markdown');\r\n this.dispatchEvent(\r\n new CustomEvent<MarkdownErrorEventDetail>('markdown-error', {\r\n detail: { error: this.error },\r\n bubbles: true,\r\n composed: true\r\n })\r\n );\r\n }\r\n this.loading = false;\r\n }\r\n\r\n render() {\r\n if (this.loading) return html`<div part=\"loading\">Loading content...</div>`;\r\n if (this.error) return html`<div part=\"error\">Error loading content.</div>`;\r\n const source = this.src ? this.fetched : this.content;\r\n if (!source) return nothing;\r\n const rendered = DOMPurify.sanitize(marked.parse(source, { gfm: true, breaks: true, async: false }));\r\n return html`<div part=\"body\">${unsafeHTML(rendered)}</div>`;\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/shared/section-styles.ts"],"sourcesContent":["import { css } from 'lit';\r\n\r\n/**\r\n * CSS fragments shared by the CMS section components (hero, features, stats, ...), replacing the\r\n * source React library's global `Common.css` classes (`.section-title`, `.theme-inverted`, ...)\r\n * so each Lit component composes them into its own shadow root instead of re-declaring them.\r\n */\r\n\r\n/** Section heading + subheading typography. Use on `.title` / `.subtitle` selectors. */\r\nexport const sectionTitleStyles = css`\r\n font-size: var(--st-cms-text-4xl);\r\n font-weight: var(--st-font-weight-bold);\r\n color: var(--st-color-text-strong);\r\n margin: 0 0 var(--st-space-16);\r\n line-height: 1.2;\r\n`;\r\n\r\nexport const sectionSubtitleStyles = css`\r\n font-size: var(--st-cms-text-lg);\r\n color: var(--st-color-text-muted);\r\n line-height: 1.6;\r\n margin: 0 0 var(--st-space-28);\r\n`;\r\n\r\n/** Card heading + body typography. */\r\nexport const cardTitleStyles = css`\r\n font-size: var(--st-text-2xl);\r\n font-weight: var(--st-font-weight-semibold);\r\n color: var(--st-color-text-strong);\r\n margin: 0 0 var(--st-space-8);\r\n`;\r\n\r\nexport const cardDescriptionStyles = css`\r\n font-size: var(--st-text-md);\r\n color: var(--st-color-text-muted);\r\n line-height: 1.5;\r\n`;\r\n\r\n/** Outlined call-to-action link/button used by hero, promo banner, features, ... */\r\nexport const ctaLinkStyles = css`\r\n display: inline-block;\r\n padding: 12px 24px;\r\n border-radius: var(--st-radius-sm);\r\n font: inherit;\r\n text-align: center;\r\n text-decoration: none;\r\n cursor: pointer;\r\n transition: transform 0.2s ease;\r\n`;\r\n\r\n/** Maps the source's `padding` prop (none|small|medium|large) to `:host([padding=...])` rules. */\r\nexport const paddingScaleStyles = css`\r\n :host([padding='small']) { padding: var(--st-space-16); }\r\n :host([padding='medium']) { padding: var(--st-space-24); }\r\n :host([padding='large']) { padding: var(--st-space-32); }\r\n`;\r\n\r\n/** Centered title/subtitle block above a section's content. Use on a `.header` wrapper. */\r\nexport const sectionHeaderStyles = css`\r\n text-align: center;\r\n margin-bottom: var(--st-space-48);\r\n`;\r\n\r\n/** Rounded icon tile (holds an `<iconify-icon>`) used by bento cards, feature lists, ... */\r\nexport const iconTileStyles = css`\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex-shrink: 0;\r\n border-radius: var(--st-radius-lg);\r\n background: var(--st-color-subtle);\r\n color: var(--st-color-text-muted);\r\n`;\r\n\r\n/** Collapses CSS transitions/animations for users who prefer reduced motion. */\r\nexport const reducedMotionStyles = css`\r\n @media (prefers-reduced-motion: reduce) {\r\n *,\r\n *::before,\r\n *::after {\r\n transition-duration: 0.01ms !important;\r\n animation-duration: 0.01ms !important;\r\n }\r\n }\r\n`;\r\n\r\n/** Light-on-dark title/subtitle for an `inverted` section host. Place inside the host's `static styles`. */\r\nexport const invertedSectionTextStyles = css`\r\n :host([inverted]) .title {\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n :host([inverted]) .subtitle {\r\n color: var(--st-color-border);\r\n }\r\n`;\r\n"],"mappings":";AAAA,SAAS,WAAW;AASb,IAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ3B,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ9B,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAOxB,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAO9B,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYtB,IAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAO3B,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAM5B,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWvB,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAY5B,IAAM,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/menu-grid-item/MenuGridItem.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property, state } from 'lit/decorators.js';\r\n\r\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport type { MenuGridItemSelectEventDetail } from './MenuGridItemEvents';\r\n\r\n/**\r\n * One entry in an `st-menu-grid` — icon (via `slot=\"icon\"`) + title on one line, an optional\r\n * description below, and an optional corner badge (\"New\", \"Popular\", ...). A 1:1 port of\r\n * `SankhyaUI`'s React `MenuGridItem` (`SankhyaCMS/SankhyaUI/src/components/Menu`): same markup and\r\n * CSS, with its `motion` effects redone in CSS — fades up the first time it scrolls into view,\r\n * scales to 1.02 on hover / 0.98 while pressed, the icon tilts on hover, the badge pops in.\r\n * Colors come from the suite theme rather than per-item utility classes.\r\n *\r\n * An `http(s)` `href` opens in a new tab, like the source. Any other `href` fires a *cancelable*\r\n * `menu-grid-item-select` event (detail: `{ href }`) first: a host doing client-side routing calls\r\n * `event.preventDefault()` on it, which also cancels the anchor's own navigation (the source used\r\n * react-router's `Link` here; the suite apps have no router).\r\n */\r\n@customElement('st-menu-grid-item')\r\nexport class MenuGridItem extends LitElement {\r\n /** `focus()` on the element focuses its link, so `st-dropdown` can arrow-key between items. */\r\n static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true };\r\n\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n ${fontFamilyStyles}\r\n }\r\n\r\n @keyframes st-menu-grid-badge-pop {\r\n from {\r\n transform: scale(0);\r\n }\r\n 70% {\r\n transform: scale(1.12);\r\n }\r\n to {\r\n transform: scale(1);\r\n }\r\n }\r\n\r\n .menu-grid-item {\r\n display: flex;\r\n flex-direction: column;\r\n border-radius: 8px;\r\n position: relative;\r\n overflow: hidden;\r\n color: var(--st-color-text);\r\n transition:\r\n opacity 0.4s ease-out,\r\n transform 0.2s ease,\r\n background-color 0.2s ease;\r\n }\r\n\r\n .menu-grid-item.pending {\r\n opacity: 0;\r\n transform: translateY(20px);\r\n }\r\n\r\n .menu-grid-item.regular {\r\n padding: 16px;\r\n }\r\n\r\n .menu-grid-item.compact {\r\n padding: 12px;\r\n }\r\n\r\n /* Keyboard focus gets the same treatment as hover. */\r\n .menu-grid-item:hover,\r\n .menu-grid-item:has(.menu-grid-link:focus-visible) {\r\n background: var(--st-color-hover);\r\n transform: scale(1.02);\r\n }\r\n\r\n .menu-grid-item:active {\r\n transform: scale(0.98);\r\n }\r\n\r\n .menu-grid-link {\r\n display: flex;\r\n flex-direction: column;\r\n text-decoration: none;\r\n color: inherit;\r\n width: 100%;\r\n height: 100%;\r\n gap: 8px;\r\n }\r\n\r\n .menu-grid-badge {\r\n position: absolute;\r\n top: 2px;\r\n right: 8px;\r\n font-size: 0.5rem;\r\n padding: 2px 8px;\r\n border-radius: 9999px;\r\n font-weight: 500;\r\n z-index: 1;\r\n background-color: var(--st-color-text-strong);\r\n color: var(--st-color-on-solid);\r\n animation: st-menu-grid-badge-pop 0.35s ease-out;\r\n }\r\n\r\n .menu-grid-header {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n width: 100%;\r\n }\r\n\r\n .menu-grid-icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 6px;\r\n transition:\r\n background-color 0.2s ease,\r\n transform 0.2s ease;\r\n flex-shrink: 0;\r\n padding: 0;\r\n margin-bottom: 0;\r\n }\r\n\r\n .menu-grid-icon:hover {\r\n transform: rotate(5deg) scale(1.1);\r\n }\r\n\r\n .menu-grid-icon[hidden] {\r\n display: none;\r\n }\r\n\r\n .menu-grid-icon ::slotted(*) {\r\n width: 18px;\r\n height: 18px;\r\n }\r\n\r\n .menu-grid-title {\r\n font-size: 0.875rem;\r\n font-weight: 500;\r\n color: var(--st-color-text-strong);\r\n transition: color 0.2s ease;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n margin-bottom: 0;\r\n }\r\n\r\n .menu-grid-description {\r\n font-size: 0.75rem;\r\n color: var(--st-color-text-muted);\r\n display: -webkit-box;\r\n -webkit-box-orient: vertical;\r\n overflow: hidden;\r\n line-height: 1.4;\r\n transition: color 0.2s ease;\r\n }\r\n\r\n .menu-grid-item.compact .menu-grid-header {\r\n gap: 8px;\r\n }\r\n\r\n .menu-grid-item.compact .menu-grid-icon {\r\n width: 24px;\r\n height: 24px;\r\n }\r\n\r\n .menu-grid-item.compact .menu-grid-icon ::slotted(*) {\r\n width: 14px;\r\n height: 14px;\r\n }\r\n\r\n .menu-grid-item.compact .menu-grid-title {\r\n font-size: 0.75rem;\r\n }\r\n\r\n .menu-grid-item.compact .menu-grid-description {\r\n font-size: 0.75rem;\r\n }\r\n\r\n .menu-grid-header.icon-only {\r\n justify-content: center;\r\n }\r\n\r\n @media (max-width: 480px) {\r\n .menu-grid-header {\r\n gap: 8px;\r\n }\r\n\r\n .menu-grid-icon {\r\n width: 28px;\r\n height: 28px;\r\n }\r\n\r\n .menu-grid-icon ::slotted(*) {\r\n width: 16px;\r\n height: 16px;\r\n }\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .menu-grid-item,\r\n .menu-grid-icon {\r\n transition: none;\r\n }\r\n\r\n .menu-grid-item.pending {\r\n opacity: 1;\r\n transform: none;\r\n }\r\n\r\n .menu-grid-badge {\r\n animation: none;\r\n }\r\n }\r\n `;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n @property({ type: String })\r\n description = '';\r\n\r\n @property({ type: String })\r\n href = '';\r\n\r\n /** Small corner label, e.g. \"New\"/\"Beta\" — omit for none. */\r\n @property({ type: String })\r\n badge = '';\r\n\r\n @property({ type: Boolean, reflect: true })\r\n compact = false;\r\n\r\n /** Suppresses the description even when `description` is set (source: `showDescription`, default `true`). */\r\n @property({ type: Boolean, attribute: 'show-description' })\r\n showDescription = true;\r\n\r\n /** Whether `slot=\"icon\"` has content, so an omitted icon leaves no empty box. */\r\n @state() private hasIcon = false;\r\n\r\n /** True until the item first scrolls into view (the source's `whileInView ... once`). */\r\n @state() private pending = true;\r\n\r\n private observer?: IntersectionObserver;\r\n\r\n connectedCallback(): void {\r\n super.connectedCallback();\r\n if (typeof IntersectionObserver === 'undefined') {\r\n this.pending = false;\r\n return;\r\n }\r\n this.observer = new IntersectionObserver((entries) => {\r\n if (entries.some((entry) => entry.isIntersecting)) {\r\n this.pending = false;\r\n this.observer?.disconnect();\r\n }\r\n });\r\n this.observer.observe(this);\r\n }\r\n\r\n disconnectedCallback(): void {\r\n this.observer?.disconnect();\r\n super.disconnectedCallback();\r\n }\r\n\r\n private onIconSlotChange = (event: Event): void => {\r\n this.hasIcon = (event.target as HTMLSlotElement).assignedNodes({ flatten: true }).length > 0;\r\n };\r\n\r\n private get isExternal(): boolean {\r\n return this.href.startsWith('http');\r\n }\r\n\r\n private onClick = (event: MouseEvent): void => {\r\n if (this.isExternal) return;\r\n const selectEvent = new CustomEvent<MenuGridItemSelectEventDetail>('menu-grid-item-select', {\r\n detail: { href: this.href },\r\n bubbles: true,\r\n composed: true,\r\n cancelable: true\r\n });\r\n this.dispatchEvent(selectEvent);\r\n if (selectEvent.defaultPrevented) event.preventDefault();\r\n };\r\n\r\n render() {\r\n const iconOnly = this.hasIcon && !this.title;\r\n return html`\r\n <div class=\"menu-grid-item ${this.compact ? 'compact' : 'regular'} ${this.pending ? 'pending' : ''}\" part=\"item\">\r\n <a\r\n part=\"link\"\r\n class=\"menu-grid-link\"\r\n href=${this.href}\r\n target=${this.isExternal ? '_blank' : '_self'}\r\n rel=${this.isExternal ? 'noopener noreferrer' : nothing}\r\n @click=${this.onClick}\r\n >\r\n ${this.badge ? html`<span part=\"badge\" class=\"menu-grid-badge\">${this.badge}</span>` : nothing}\r\n <span class=\"menu-grid-header ${iconOnly ? 'icon-only' : ''}\" part=\"header\">\r\n <span class=\"menu-grid-icon\" part=\"icon\" ?hidden=${!this.hasIcon}><slot name=\"icon\" @slotchange=${this.onIconSlotChange}></slot></span>\r\n ${this.title ? html`<span part=\"title\" class=\"menu-grid-title\">${this.title}</span>` : nothing}\r\n </span>\r\n ${this.description && this.showDescription\r\n ? html`<span part=\"description\" class=\"menu-grid-description\">${this.description}</span>`\r\n : nothing}\r\n </a>\r\n </div>\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/stats/Stats.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\n\r\nimport { controlBaseStyles, rootFontFamilyStyles } from '../shared/styles';\r\n\r\nexport interface StatItem {\r\n value: string;\r\n label: string;\r\n description?: string;\r\n}\r\n\r\n/**\r\n * Responsive grid of headline numbers with a label and optional description. Port of React `Stats`.\r\n * `inverted` puts it on the dark band (`--st-cms-band-dark-bg`), which stays dark in the dark theme.\r\n *\r\n * @cssprop --st-stats-padding - Overrides the block's padding.\r\n */\r\n@customElement('st-stats')\r\nexport class Stats extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n box-sizing: border-box;\r\n /* !important: a page-level reset (e.g. Tailwind Preflight) otherwise zeroes a shadow host's\r\n padding; override with --st-stats-padding instead. */\r\n padding: var(--st-stats-padding, var(--st-space-48) var(--st-space-24)) !important;\r\n background-color: var(--st-color-surface);\r\n border-top: 1px solid var(--st-color-divider);\r\n border-bottom: 1px solid var(--st-color-divider);\r\n ${rootFontFamilyStyles}\r\n }\r\n\r\n :host([inverted]) {\r\n background-color: var(--st-cms-band-dark-bg);\r\n border-color: transparent;\r\n }\r\n\r\n .grid {\r\n max-width: var(--st-cms-container-max);\r\n margin: 0 auto;\r\n display: grid;\r\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\r\n gap: var(--st-space-40);\r\n }\r\n\r\n .item {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n text-align: center;\r\n gap: var(--st-space-8);\r\n }\r\n\r\n .value {\r\n font-size: var(--st-cms-text-3xl);\r\n font-weight: var(--st-font-weight-bold);\r\n color: var(--st-color-text-strong);\r\n line-height: 1;\r\n letter-spacing: -0.02em;\r\n }\r\n\r\n .label {\r\n font-size: var(--st-text-xl);\r\n font-weight: var(--st-font-weight-semibold);\r\n color: var(--st-color-text-muted);\r\n text-transform: uppercase;\r\n letter-spacing: var(--st-tracking-wide);\r\n }\r\n\r\n .description {\r\n font-size: var(--st-text-sm);\r\n color: var(--st-color-text-faint);\r\n max-width: 200px;\r\n }\r\n\r\n :host([inverted]) .value {\r\n color: var(--st-cms-band-dark-color);\r\n }\r\n\r\n :host([inverted]) .label,\r\n :host([inverted]) .description {\r\n color: color-mix(in oklch, var(--st-cms-band-dark-color) 75%, transparent);\r\n }\r\n\r\n @media (max-width: 768px) {\r\n :host {\r\n padding: var(--st-stats-padding, var(--st-space-40) var(--st-space-24)) !important;\r\n }\r\n .grid {\r\n grid-template-columns: repeat(2, 1fr);\r\n gap: var(--st-space-24);\r\n }\r\n .value {\r\n font-size: var(--st-cms-text-xl);\r\n }\r\n }\r\n `;\r\n\r\n @property({ attribute: false })\r\n items: StatItem[] = [];\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n render() {\r\n return html`\r\n <div class=\"grid\" part=\"grid\">\r\n ${this.items.map(\r\n (stat) => html`\r\n <div class=\"item\" part=\"item\">\r\n <span class=\"value\" part=\"value\">${stat.value}</span>\r\n <span class=\"label\" part=\"label\">${stat.label}</span>\r\n ${stat.description ? html`<span class=\"description\" part=\"description\">${stat.description}</span>` : nothing}\r\n </div>\r\n `\r\n )}\r\n </div>\r\n `;\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;AAAA,SAAS,YAAY,KAAK,MAAM,eAAe;AAC/C,SAAS,eAAe,gBAAgB;AAiBjC,IAAM,QAAN,cAAoB,WAAW;AAAA,EAA/B;AAAA;AAmFL,iBAAoB,CAAC;AAGrB,oBAAW;AAAA;AAAA,EAEX,SAAS;AACP,WAAO;AAAA;AAAA,UAED,KAAK,MAAM;AAAA,MACX,CAAC,SAAS;AAAA;AAAA,iDAE6B,KAAK,KAAK;AAAA,iDACV,KAAK,KAAK;AAAA,gBAC3C,KAAK,cAAc,oDAAoD,KAAK,WAAW,YAAY,OAAO;AAAA;AAAA;AAAA,IAGlH,CAAC;AAAA;AAAA;AAAA,EAGP;AACF;AAvGa,MACJ,SAAS;AAAA,MACZ,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAWf,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsE1B;AAAA,EADC,SAAS,EAAE,WAAW,MAAM,CAAC;AAAA,GAlFnB,MAmFX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GArF/B,MAsFX;AAtFW,QAAN;AAAA,EADN,cAAc,UAAU;AAAA,GACZ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/card/Card.ts"],"sourcesContent":["import { LitElement, css, html } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\n\r\nimport { controlBaseStyles, cardShellStyles, fontFamilyStyles } from '../shared/styles';\r\n\r\n/**\r\n * A surfaced container — content goes in the default slot. Ports `SankhyaUI`'s React `Card`\r\n * (`variant`, `padding`, `elevation`, `hoverable`, `inverted`); `onClick` is just a native `click`\r\n * listener on the element. `padding` takes `none | small | medium | large` (the source's\r\n * `sm|md|lg`, spelled like `paddingScaleStyles`); `elevation` takes `none | sm | md | lg`.\r\n */\r\n@customElement('st-card')\r\nexport class Card extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n ${fontFamilyStyles}\r\n ${cardShellStyles}\r\n border-radius: var(--st-radius-lg);\r\n overflow: hidden;\r\n position: relative;\r\n transition:\r\n transform 0.3s ease,\r\n box-shadow 0.3s ease,\r\n border-color 0.3s ease;\r\n }\r\n\r\n :host([variant='bordered']) {\r\n border-color: var(--st-color-border-strong);\r\n }\r\n\r\n :host([elevation='sm']) {\r\n box-shadow: 0 1px 2px var(--st-shadow-color-sm);\r\n }\r\n\r\n :host([elevation='md']) {\r\n box-shadow: 0 4px 6px -1px var(--st-shadow-color-md);\r\n }\r\n\r\n :host([elevation='lg']) {\r\n box-shadow: 0 10px 15px -3px var(--st-shadow-color-lg);\r\n }\r\n\r\n :host([hoverable]:hover) {\r\n transform: translateY(-4px);\r\n box-shadow: 0 20px 25px -5px var(--st-shadow-color-xl);\r\n border-color: var(--st-color-border-strong);\r\n }\r\n\r\n :host([inverted]) {\r\n background: var(--st-color-text-strong);\r\n color: var(--st-color-on-solid);\r\n border-color: var(--st-color-text-strong);\r\n }\r\n\r\n .body {\r\n padding: var(--st-space-24);\r\n }\r\n\r\n :host([padding='none']) .body {\r\n padding: 0;\r\n }\r\n\r\n :host([padding='small']) .body {\r\n padding: var(--st-space-16);\r\n }\r\n\r\n :host([padding='large']) .body {\r\n padding: var(--st-space-32);\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n :host {\r\n transition: none;\r\n }\r\n\r\n :host([hoverable]:hover) {\r\n transform: none;\r\n }\r\n }\r\n `;\r\n\r\n @property({ type: String, reflect: true })\r\n variant: 'default' | 'bordered' = 'default';\r\n\r\n @property({ type: String, reflect: true })\r\n padding: 'none' | 'small' | 'medium' | 'large' = 'medium';\r\n\r\n @property({ type: String, reflect: true })\r\n elevation: 'none' | 'sm' | 'md' | 'lg' = 'sm';\r\n\r\n @property({ type: Boolean, reflect: true })\r\n hoverable = false;\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n render() {\r\n return html`<div class=\"body\" part=\"body\"><slot></slot></div>`;\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;AAAA,SAAS,YAAY,KAAK,YAAY;AACtC,SAAS,eAAe,gBAAgB;AAWjC,IAAM,OAAN,cAAmB,WAAW;AAAA,EAA9B;AAAA;AAyEL,mBAAkC;AAGlC,mBAAiD;AAGjD,qBAAyC;AAGzC,qBAAY;AAGZ,oBAAW;AAAA;AAAA,EAEX,SAAS;AACP,WAAO;AAAA,EACT;AACF;AA1Fa,KACJ,SAAS;AAAA,MACZ,iBAAiB;AAAA;AAAA;AAAA;AAAA,QAIf,gBAAgB;AAAA,QAChB,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkErB;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GAxE9B,KAyEX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GA3E9B,KA4EX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GA9E9B,KA+EX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GAjF/B,KAkFX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GApF/B,KAqFX;AArFW,OAAN;AAAA,EADN,cAAc,SAAS;AAAA,GACX;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/features-section/FeaturesSection.ts","../src/features-section/FeatureItem.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\n\r\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport { sectionSubtitleStyles, sectionTitleStyles, sectionHeaderStyles } from '../shared/section-styles';\r\nimport './FeatureItem';\r\n\r\n/** Data for one tile when using the `items` property (mirrors `st-feature-item`'s properties). */\r\nexport interface FeatureItemData {\r\n icon?: string;\r\n title: string;\r\n description: string;\r\n href?: string;\r\n}\r\n\r\n/**\r\n * A titled grid of feature tiles. Ports `SankhyaUI`'s React `FeaturesSection`: tiles come from the\r\n * `items` property, from slotted `st-feature-item` elements (the source's `children`), or both\r\n * (slotted first). `columns` sets the grid width (default 2; one column below 768px). `inverted`\r\n * is passed on to the `items` tiles; slotted tiles need their own `inverted` attribute.\r\n *\r\n * @cssprop --st-features-section-padding - Overrides the section's padding.\r\n */\r\n@customElement('st-features-section')\r\nexport class FeaturesSection extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n ${fontFamilyStyles}\r\n /* !important: a page-level reset (e.g. Tailwind Preflight) otherwise zeroes a shadow host's\r\n padding; override with --st-features-section-padding instead. */\r\n padding: var(--st-features-section-padding, var(--st-cms-section-padding) var(--st-space-24)) !important;\r\n background: var(--st-color-surface);\r\n }\r\n\r\n :host([inverted]) {\r\n background: var(--st-color-text-strong);\r\n }\r\n\r\n .container {\r\n max-width: var(--st-cms-container-max);\r\n margin: 0 auto;\r\n }\r\n\r\n .header {\r\n ${sectionHeaderStyles}\r\n }\r\n\r\n .title {\r\n ${sectionTitleStyles}\r\n margin: 0;\r\n }\r\n\r\n .subtitle {\r\n ${sectionSubtitleStyles}\r\n margin: 0 auto;\r\n }\r\n\r\n :host([inverted]) .title,\r\n :host([inverted]) .subtitle {\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n .grid {\r\n display: grid;\r\n grid-template-columns: repeat(var(--features-columns, 2), 1fr);\r\n gap: var(--st-space-32);\r\n }\r\n\r\n @media (max-width: 768px) {\r\n :host {\r\n padding: var(--st-features-section-padding, var(--st-space-48) var(--st-space-16)) !important;\r\n }\r\n\r\n .grid {\r\n grid-template-columns: 1fr;\r\n }\r\n }\r\n `;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n @property({ type: String })\r\n subtitle = '';\r\n\r\n /** Applied to every tile built from `items`. */\r\n @property({ type: String, attribute: 'action-label' })\r\n actionLabel = 'Learn more';\r\n\r\n @property({ type: Number })\r\n columns = 0;\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n /** Tiles to render (property only). */\r\n @property({ attribute: false })\r\n items: FeatureItemData[] = [];\r\n\r\n render() {\r\n const gridStyle = this.columns ? `--features-columns: ${this.columns}` : nothing;\r\n return html`\r\n <section class=\"container\" part=\"container\">\r\n <div class=\"header\" part=\"header\">\r\n <div class=\"title\" part=\"title\">${this.title}</div>\r\n ${this.subtitle ? html`<div class=\"subtitle\" part=\"subtitle\">${this.subtitle}</div>` : nothing}\r\n </div>\r\n <div class=\"grid\" part=\"grid\" style=${gridStyle}>\r\n <slot></slot>\r\n ${this.items.map(\r\n (item) => html`\r\n <st-feature-item\r\n .icon=${item.icon ?? ''}\r\n .title=${item.title}\r\n .description=${item.description}\r\n .href=${item.href ?? ''}\r\n .actionLabel=${this.actionLabel}\r\n ?inverted=${this.inverted}\r\n ></st-feature-item>\r\n `\r\n )}\r\n </div>\r\n </section>\r\n `;\r\n }\r\n}\r\n","import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\nimport 'iconify-icon';\r\n\r\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport { cardDescriptionStyles, cardTitleStyles } from '../shared/section-styles';\r\nimport '../card';\r\nimport '../markdown';\r\n\r\n/**\r\n * One feature tile for `st-features-section`: optional icon, title, Markdown description and an\r\n * optional \"Learn more\" link, rendered on an `st-card`. `icon` is an Iconify name (e.g.\r\n * `mdi:rocket`). The link is a plain `<a>` (the source used react-router's `Link` for non-http\r\n * hrefs; there is no Lit equivalent). The click is composed, so an SPA router can intercept it\r\n * (e.g. via `event.composedPath()`) and navigate client-side; `http(s)` links open in a new tab.\r\n */\r\n@customElement('st-feature-item')\r\nexport class FeatureItem extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n ${fontFamilyStyles}\r\n }\r\n\r\n st-card {\r\n height: 100%;\r\n }\r\n\r\n .content {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: flex-start;\r\n gap: var(--st-space-16);\r\n height: 100%;\r\n }\r\n\r\n .icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 48px;\r\n height: 48px;\r\n border-radius: var(--st-radius-lg);\r\n background: var(--st-color-subtle);\r\n color: var(--st-color-text-strong);\r\n margin-bottom: var(--st-space-8);\r\n font-size: 24px;\r\n }\r\n\r\n :host([inverted]) .icon {\r\n background: var(--st-color-text-muted);\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n .title {\r\n ${cardTitleStyles}\r\n margin: 0;\r\n }\r\n\r\n .description {\r\n ${cardDescriptionStyles}\r\n margin: 0;\r\n }\r\n\r\n :host([inverted]) .title,\r\n :host([inverted]) .description {\r\n color: inherit;\r\n }\r\n\r\n .link {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--st-space-4);\r\n margin-top: auto;\r\n color: var(--st-color-text-muted);\r\n font-weight: var(--st-font-weight-medium);\r\n font-size: var(--st-text-md);\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n }\r\n\r\n .link:hover {\r\n color: var(--st-color-text-strong);\r\n text-decoration: underline;\r\n }\r\n\r\n :host([inverted]) .link,\r\n :host([inverted]) .link:hover {\r\n color: inherit;\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .link {\r\n transition: none;\r\n }\r\n }\r\n `;\r\n\r\n /** Iconify icon name, e.g. `mdi:rocket`. */\r\n @property({ type: String })\r\n icon = '';\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n /** Markdown. */\r\n @property({ type: String })\r\n description = '';\r\n\r\n @property({ type: String })\r\n href = '';\r\n\r\n @property({ type: String, attribute: 'action-label' })\r\n actionLabel = 'Learn more';\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n render() {\r\n const external = this.href.startsWith('http');\r\n return html`\r\n <st-card hoverable elevation=\"sm\" ?inverted=${this.inverted} part=\"card\">\r\n <div class=\"content\" part=\"content\">\r\n ${this.icon\r\n ? html`<div class=\"icon\" part=\"icon\"><iconify-icon icon=${this.icon}></iconify-icon></div>`\r\n : nothing}\r\n <h3 class=\"title\" part=\"title\">${this.title}</h3>\r\n <st-markdown class=\"description\" part=\"description\" .content=${this.description}></st-markdown>\r\n ${this.href\r\n ? html`\r\n <a\r\n class=\"link\"\r\n part=\"link\"\r\n href=${this.href}\r\n target=${external ? '_blank' : '_self'}\r\n rel=${external ? 'noopener noreferrer' : nothing}\r\n >\r\n ${this.actionLabel} <span>&rarr;</span>\r\n </a>\r\n `\r\n : nothing}\r\n </div>\r\n </st-card>\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":["LitElement","css","html","nothing","customElement","property","LitElement","nothing","html","css","property","customElement"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/footer/Footer.ts"],"sourcesContent":["import { LitElement, PropertyValues, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\nimport 'iconify-icon';\r\n\r\nimport { controlBaseStyles, rootFontFamilyStyles } from '../shared/styles';\r\n\r\nexport interface FooterLink {\r\n label: string;\r\n href: string;\r\n}\r\n\r\nexport interface FooterColumn {\r\n title: string;\r\n links: FooterLink[];\r\n}\r\n\r\nexport interface FooterSocialLink {\r\n /** Iconify icon name, e.g. `mdi:github`. */\r\n icon: string;\r\n href: string;\r\n}\r\n\r\n/** Fired when an internal footer link is activated — cancelable, so an SPA can `preventDefault()` and route instead. */\r\nexport interface FooterLinkEventDetail {\r\n href: string;\r\n}\r\n\r\n/**\r\n * The footer, in two layouts:\r\n *\r\n * - **Bar** (default): a copyright line plus an optional \"powered by\" link — what the suite's\r\n * authenticated apps use.\r\n * - **Site**: when `columns`, `socialLinks`, `description` or `imageSrc` is set, the footer becomes a\r\n * marketing-site footer — brand (logo/company name, description, social icons), link columns and a\r\n * bottom bar with the copyright and \"powered by\".\r\n *\r\n * Fires a cancelable `footer-link` event (detail `{ href }`) when an internal link is clicked.\r\n */\r\n@customElement('st-footer')\r\nexport class Footer extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: var(--st-space-16);\r\n flex-wrap: wrap;\r\n /* !important on padding/border-top only: a shadow host's own :host rule always loses to ANY\r\n * rule the consuming page has for the same property on that element, regardless of\r\n * specificity — so a page that resets margin/padding/border on every element (e.g. Tailwind\r\n * Preflight, which every app but Template Hub loads) silently zeroes this footer's padding\r\n * and top border unless these two win the conflict outright via !important. */\r\n padding: var(--st-space-16) var(--st-space-28) !important;\r\n border-top: 1px solid var(--st-color-border) !important;\r\n color: var(--st-color-text-muted);\r\n font-size: var(--st-text-xs);\r\n ${rootFontFamilyStyles}\r\n }\r\n\r\n .powered-by {\r\n color: inherit;\r\n text-decoration: none;\r\n font-weight: var(--st-font-weight-semibold);\r\n }\r\n\r\n .powered-by:hover {\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n :host([inverted]) {\r\n background: var(--st-color-text-strong);\r\n color: var(--st-color-on-solid);\r\n border-top-color: transparent !important;\r\n }\r\n\r\n /* Site layout */\r\n :host([site]) {\r\n display: block;\r\n padding: 64px var(--st-space-28) 32px !important;\r\n font-size: var(--st-text-sm);\r\n }\r\n\r\n .site {\r\n max-width: 1200px;\r\n margin: 0 auto;\r\n }\r\n\r\n .grid {\r\n display: grid;\r\n grid-template-columns: 2fr repeat(3, 1fr);\r\n gap: 64px;\r\n margin-bottom: 64px;\r\n }\r\n\r\n .brand {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n }\r\n\r\n .logo {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 1.25rem;\r\n font-weight: 700;\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n .logo-img {\r\n height: 32px;\r\n width: auto;\r\n }\r\n\r\n .description {\r\n margin: 0;\r\n max-width: 300px;\r\n line-height: 1.6;\r\n }\r\n\r\n .social {\r\n display: flex;\r\n gap: 16px;\r\n margin-top: 16px;\r\n }\r\n\r\n .social-link,\r\n .link {\r\n color: inherit;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n }\r\n\r\n .social-link:hover,\r\n .link:hover {\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n .column-title {\r\n margin: 0 0 24px;\r\n font-size: var(--st-text-xs);\r\n font-weight: var(--st-font-weight-semibold);\r\n color: var(--st-color-text-strong);\r\n text-transform: uppercase;\r\n letter-spacing: 0.05em;\r\n }\r\n\r\n .links {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n }\r\n\r\n .bottom {\r\n padding-top: 32px;\r\n border-top: 1px solid var(--st-color-border);\r\n font-size: var(--st-text-xs);\r\n }\r\n\r\n .bottom-text {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n }\r\n\r\n .bottom-text .powered-by {\r\n font-size: 0.85em;\r\n font-weight: inherit;\r\n opacity: 0.8;\r\n }\r\n\r\n @media (max-width: 1024px) {\r\n .grid {\r\n grid-template-columns: repeat(3, 1fr);\r\n gap: 48px;\r\n }\r\n }\r\n\r\n @media (max-width: 768px) {\r\n .grid {\r\n grid-template-columns: 1fr;\r\n gap: 40px;\r\n }\r\n\r\n .bottom {\r\n text-align: center;\r\n }\r\n }\r\n\r\n :host([site][inverted]) .logo,\r\n :host([site][inverted]) .column-title,\r\n :host([site][inverted]) .social-link:hover,\r\n :host([site][inverted]) .link:hover {\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n :host([site][inverted]) .bottom {\r\n border-top-color: color-mix(in oklch, var(--st-color-on-solid) 20%, var(--st-color-text-strong));\r\n }\r\n `;\r\n\r\n /** Inverts the footer's color roles (light-on-dark instead of dark-on-light) — matches the\r\n * source component's `inverted` (from its shared `BaseProps`), same as `st-header`'s. */\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n /** Used to build the default `copyright` line (`© {year} {companyName}`) when `copyright` isn't set explicitly. */\r\n @property({ type: String, attribute: 'company-name' })\r\n companyName = '';\r\n\r\n /** Overrides the default computed copyright line entirely. */\r\n @property({ type: String })\r\n copyright = '';\r\n\r\n @property({ type: String, attribute: 'powered-by' })\r\n poweredBy = '';\r\n\r\n @property({ type: String, attribute: 'powered-by-link' })\r\n poweredByLink = '';\r\n\r\n /** App version, rendered as `v{version}` after the copyright line — for apps that show their own\r\n * version in the footer rather than the header title. */\r\n @property({ type: String })\r\n version = '';\r\n\r\n /** Logo shown in the brand block (site layout). */\r\n @property({ type: String, attribute: 'image-src' })\r\n imageSrc = '';\r\n\r\n /** Short blurb under the logo (site layout). */\r\n @property({ type: String })\r\n description = '';\r\n\r\n /** Link columns (site layout). */\r\n @property({ attribute: false })\r\n columns: FooterColumn[] = [];\r\n\r\n /** Social icon links under the description (site layout). */\r\n @property({ attribute: false })\r\n socialLinks: FooterSocialLink[] = [];\r\n\r\n private get isSite(): boolean {\r\n return !!(this.columns.length || this.socialLinks.length || this.description || this.imageSrc);\r\n }\r\n\r\n private get resolvedCopyright(): string {\r\n if (this.copyright) return this.copyright;\r\n if (this.companyName) return `© ${new Date().getFullYear()} ${this.companyName}`;\r\n return `© ${new Date().getFullYear()}`;\r\n }\r\n\r\n protected willUpdate(changed: PropertyValues): void {\r\n if (changed.size) this.toggleAttribute('site', this.isSite);\r\n }\r\n\r\n private onLinkClick(event: MouseEvent, href: string): void {\r\n const select = new CustomEvent<FooterLinkEventDetail>('footer-link', {\r\n detail: { href },\r\n bubbles: true,\r\n composed: true,\r\n cancelable: true\r\n });\r\n this.dispatchEvent(select);\r\n if (select.defaultPrevented) event.preventDefault();\r\n }\r\n\r\n private renderLink(link: FooterLink) {\r\n return /^https?:/i.test(link.href)\r\n ? html`<a part=\"link\" class=\"link\" href=${link.href} target=\"_blank\" rel=\"noopener noreferrer\">${link.label}</a>`\r\n : html`<a part=\"link\" class=\"link\" href=${link.href} @click=${(event: MouseEvent) => this.onLinkClick(event, link.href)}>${link.label}</a>`;\r\n }\r\n\r\n private renderPoweredBy() {\r\n return this.poweredBy\r\n ? html`\r\n <a part=\"powered-by\" class=\"powered-by\" href=${this.poweredByLink || '#'} target=\"_blank\" rel=\"noopener noreferrer\">\r\n ${this.poweredBy}\r\n </a>\r\n `\r\n : nothing;\r\n }\r\n\r\n private renderSite() {\r\n return html`\r\n <div class=\"site\" part=\"site\">\r\n <div class=\"grid\">\r\n <div class=\"brand\" part=\"brand\">\r\n ${this.imageSrc || this.companyName\r\n ? html`<div class=\"logo\">\r\n ${this.imageSrc ? html`<img class=\"logo-img\" src=${this.imageSrc} alt=${this.companyName || 'Logo'} />` : nothing}\r\n ${this.companyName ? html`<span>${this.companyName}</span>` : nothing}\r\n </div>`\r\n : nothing}\r\n ${this.description ? html`<p class=\"description\">${this.description}</p>` : nothing}\r\n ${this.socialLinks.length\r\n ? html`<div class=\"social\">\r\n ${this.socialLinks.map(\r\n social => html`<a part=\"social\" class=\"social-link\" href=${social.href} target=\"_blank\" rel=\"noopener noreferrer\" aria-label=${social.icon}>\r\n <iconify-icon icon=${social.icon} width=\"24\" height=\"24\"></iconify-icon>\r\n </a>`\r\n )}\r\n </div>`\r\n : nothing}\r\n </div>\r\n ${this.columns.map(\r\n column => html`<div class=\"column\" part=\"column\">\r\n <h4 class=\"column-title\">${column.title}</h4>\r\n <div class=\"links\">${column.links.map(link => this.renderLink(link))}</div>\r\n </div>`\r\n )}\r\n </div>\r\n <div class=\"bottom\" part=\"bottom\">\r\n <div class=\"bottom-text\">\r\n <span part=\"copyright\">${this.resolvedCopyright}</span>\r\n ${this.version ? html`<span part=\"version\">v${this.version}</span>` : nothing} ${this.renderPoweredBy()}\r\n </div>\r\n </div>\r\n </div>\r\n `;\r\n }\r\n\r\n render() {\r\n if (this.isSite) return this.renderSite();\r\n return html`\r\n <span part=\"copyright\">${this.resolvedCopyright}</span>\r\n ${this.version ? html`<span part=\"version\">v${this.version}</span>` : nothing} ${this.renderPoweredBy()}\r\n `;\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;AAAA,SAAS,YAA4B,KAAK,MAAM,eAAe;AAC/D,SAAS,eAAe,gBAAgB;AACxC,OAAO;AAqCA,IAAM,SAAN,cAAqB,WAAW;AAAA,EAAhC;AAAA;AAuKL,oBAAW;AAIX,uBAAc;AAId,qBAAY;AAGZ,qBAAY;AAGZ,yBAAgB;AAKhB,mBAAU;AAIV,oBAAW;AAIX,uBAAc;AAId,mBAA0B,CAAC;AAI3B,uBAAkC,CAAC;AAAA;AAAA,EAEnC,IAAY,SAAkB;AAC5B,WAAO,CAAC,EAAE,KAAK,QAAQ,UAAU,KAAK,YAAY,UAAU,KAAK,eAAe,KAAK;AAAA,EACvF;AAAA,EAEA,IAAY,oBAA4B;AACtC,QAAI,KAAK,UAAW,QAAO,KAAK;AAChC,QAAI,KAAK,YAAa,QAAO,SAAK,oBAAI,KAAK,GAAE,YAAY,CAAC,IAAI,KAAK,WAAW;AAC9E,WAAO,SAAK,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,EACtC;AAAA,EAEU,WAAW,SAA+B;AAClD,QAAI,QAAQ,KAAM,MAAK,gBAAgB,QAAQ,KAAK,MAAM;AAAA,EAC5D;AAAA,EAEQ,YAAY,OAAmB,MAAoB;AACzD,UAAM,SAAS,IAAI,YAAmC,eAAe;AAAA,MACnE,QAAQ,EAAE,KAAK;AAAA,MACf,SAAS;AAAA,MACT,UAAU;AAAA,MACV,YAAY;AAAA,IACd,CAAC;AACD,SAAK,cAAc,MAAM;AACzB,QAAI,OAAO,iBAAkB,OAAM,eAAe;AAAA,EACpD;AAAA,EAEQ,WAAW,MAAkB;AACnC,WAAO,YAAY,KAAK,KAAK,IAAI,IAC7B,wCAAwC,KAAK,IAAI,8CAA8C,KAAK,KAAK,SACzG,wCAAwC,KAAK,IAAI,WAAW,CAAC,UAAsB,KAAK,YAAY,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,KAAK;AAAA,EACzI;AAAA,EAEQ,kBAAkB;AACxB,WAAO,KAAK,YACR;AAAA,yDACiD,KAAK,iBAAiB,GAAG;AAAA,cACpE,KAAK,SAAS;AAAA;AAAA,YAGpB;AAAA,EACN;AAAA,EAEQ,aAAa;AACnB,WAAO;AAAA;AAAA;AAAA;AAAA,cAIG,KAAK,YAAY,KAAK,cACpB;AAAA,oBACI,KAAK,WAAW,iCAAiC,KAAK,QAAQ,QAAQ,KAAK,eAAe,MAAM,QAAQ,OAAO;AAAA,oBAC/G,KAAK,cAAc,aAAa,KAAK,WAAW,YAAY,OAAO;AAAA,0BAEvE,OAAO;AAAA,cACT,KAAK,cAAc,8BAA8B,KAAK,WAAW,SAAS,OAAO;AAAA,cACjF,KAAK,YAAY,SACf;AAAA,oBACI,KAAK,YAAY;AAAA,MACjB,YAAU,iDAAiD,OAAO,IAAI,yDAAyD,OAAO,IAAI;AAAA,2CACnH,OAAO,IAAI;AAAA;AAAA,IAEpC,CAAC;AAAA,0BAEH,OAAO;AAAA;AAAA,YAEX,KAAK,QAAQ;AAAA,MACb,YAAU;AAAA,yCACmB,OAAO,KAAK;AAAA,mCAClB,OAAO,MAAM,IAAI,UAAQ,KAAK,WAAW,IAAI,CAAC,CAAC;AAAA;AAAA,IAExE,CAAC;AAAA;AAAA;AAAA;AAAA,qCAI0B,KAAK,iBAAiB;AAAA,cAC7C,KAAK,UAAU,6BAA6B,KAAK,OAAO,YAAY,OAAO,IAAI,KAAK,gBAAgB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKjH;AAAA,EAEA,SAAS;AACP,QAAI,KAAK,OAAQ,QAAO,KAAK,WAAW;AACxC,WAAO;AAAA,+BACoB,KAAK,iBAAiB;AAAA,QAC7C,KAAK,UAAU,6BAA6B,KAAK,OAAO,YAAY,OAAO,IAAI,KAAK,gBAAgB,CAAC;AAAA;AAAA,EAE3G;AACF;AAnSa,OACJ,SAAS;AAAA,MACZ,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAiBf,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoJ1B;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GAtK/B,OAuKX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,eAAe,CAAC;AAAA,GA1K1C,OA2KX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GA9Kf,OA+KX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,aAAa,CAAC;AAAA,GAjLxC,OAkLX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,kBAAkB,CAAC;AAAA,GApL7C,OAqLX;AAKA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAzLf,OA0LX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,YAAY,CAAC;AAAA,GA7LvC,OA8LX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAjMf,OAkMX;AAIA;AAAA,EADC,SAAS,EAAE,WAAW,MAAM,CAAC;AAAA,GArMnB,OAsMX;AAIA;AAAA,EADC,SAAS,EAAE,WAAW,MAAM,CAAC;AAAA,GAzMnB,OA0MX;AA1MW,SAAN;AAAA,EADN,cAAc,WAAW;AAAA,GACb;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/menu-item/MenuItem.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property, state } from 'lit/decorators.js';\r\n\r\nimport { arrowUpRightIcon } from '../shared/icons';\r\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport type { MenuItemSelectEventDetail } from './MenuItemEvents';\r\n\r\n/**\r\n * A single flat nav row — icon (`slot=\"icon\"`) + title + badge on one line, an optional\r\n * description below — as opposed to `st-menu-grid-item`'s card for a multi-column grid. A 1:1\r\n * port of `SankhyaUI`'s React `MenuItem` (`SankhyaCMS/SankhyaUI/src/components/Menu`): same\r\n * markup and CSS, with its `motion` effects redone in CSS — nudges right and scales to 1.01 on\r\n * hover / 0.99 while pressed, the icon tilts on hover, the badge pops in, the description fades\r\n * in. Colors come from the suite theme rather than per-item utility classes.\r\n *\r\n * Renders a real `<a href>` but fires a *cancelable* `menu-item-select` event (detail: `{ href }`)\r\n * before navigating — a host doing client-side routing calls `event.preventDefault()` on it (the\r\n * source used react-router's `Link` here; the suite apps have no router).\r\n */\r\n@customElement('st-menu-item')\r\nexport class MenuItem extends LitElement {\r\n /** `focus()` on the element focuses its link, so `st-dropdown` can arrow-key between items. */\r\n static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true };\r\n\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n ${fontFamilyStyles}\r\n }\r\n\r\n @keyframes st-menu-item-badge-pop {\r\n from {\r\n transform: scale(0);\r\n }\r\n 70% {\r\n transform: scale(1.12);\r\n }\r\n to {\r\n transform: scale(1);\r\n }\r\n }\r\n\r\n @keyframes st-menu-item-fade-in {\r\n from {\r\n opacity: 0;\r\n }\r\n to {\r\n opacity: 1;\r\n }\r\n }\r\n\r\n .menu-item {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 12px;\r\n padding: 12px 16px;\r\n font-size: 0.875rem;\r\n text-decoration: none;\r\n /* --st-nav-*: set by a host bar (st-header's transparent state) to recolour its nav items. */\r\n color: var(--st-nav-color, var(--st-color-text));\r\n border-radius: 6px;\r\n /* The source's 'all 0.15s', minus visibility: animating the visibility this link inherits\r\n from a dropdown panel kept it unfocusable for a frame after the panel opened. */\r\n transition-property: background-color, color, padding, transform, border-color;\r\n transition-duration: 0.15s;\r\n transition-timing-function: ease;\r\n box-sizing: border-box;\r\n }\r\n\r\n /* The source's hover nudge (x: 4px) is done with padding, not a transform: a transform would\r\n spill past a scrolling panel's edge (st-source-bar's menus) and show a horizontal scrollbar.\r\n Keyboard focus gets the same treatment as hover. */\r\n .menu-item:hover,\r\n .menu-item:focus-visible {\r\n background: var(--st-nav-hover-bg, var(--st-color-hover));\r\n color: var(--st-nav-color, var(--st-color-text-strong));\r\n padding-left: 20px;\r\n transition-duration: 0.1s;\r\n }\r\n\r\n .menu-item.compact:hover,\r\n .menu-item.compact:focus-visible {\r\n padding-left: 16px;\r\n }\r\n\r\n .menu-item:active {\r\n transform: scale(0.99);\r\n transition-duration: 0.1s;\r\n }\r\n\r\n .menu-item.active {\r\n background-color: var(--st-color-accent-subtle);\r\n color: var(--st-color-accent-text);\r\n border-left: 4px solid var(--st-color-accent);\r\n }\r\n\r\n .menu-item-icon {\r\n display: flex;\r\n flex-shrink: 0;\r\n margin-top: 2px;\r\n transition: transform 0.2s ease;\r\n }\r\n\r\n .menu-item-icon:hover {\r\n transform: rotate(5deg);\r\n }\r\n\r\n .menu-item-icon[hidden] {\r\n display: none;\r\n }\r\n\r\n .menu-item-icon ::slotted(*) {\r\n width: 16px;\r\n height: 16px;\r\n }\r\n\r\n .menu-item-content {\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .menu-item-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 8px;\r\n }\r\n\r\n .menu-item-title {\r\n font-weight: 500;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n }\r\n\r\n .menu-item-badge {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n min-width: 20px;\r\n height: 20px;\r\n padding: 0 6px;\r\n font-size: 0.75rem;\r\n font-weight: 500;\r\n border-radius: 9999px;\r\n flex-shrink: 0;\r\n background: var(--st-color-accent-subtle);\r\n color: var(--st-color-accent-text);\r\n animation: st-menu-item-badge-pop 0.35s ease-out;\r\n }\r\n\r\n .menu-item-description {\r\n display: -webkit-box;\r\n margin: 4px 0 0;\r\n font-size: 0.75rem;\r\n color: var(--st-color-text-muted);\r\n -webkit-box-orient: vertical;\r\n overflow: hidden;\r\n line-height: 1.4;\r\n animation: st-menu-item-fade-in 0.2s ease;\r\n }\r\n\r\n .menu-item.compact {\r\n padding: 8px 12px;\r\n gap: 8px;\r\n }\r\n\r\n .menu-item.compact .menu-item-icon ::slotted(*) {\r\n width: 14px;\r\n height: 14px;\r\n }\r\n\r\n .menu-item.compact .menu-item-title {\r\n font-size: 0.75rem;\r\n }\r\n\r\n .menu-item.compact .menu-item-description {\r\n font-size: 0.75rem;\r\n }\r\n\r\n /* link: a plain text link (okta.com mega-menu columns) — no box, no nudge, the badge right\r\n after the title, long titles wrap. */\r\n .menu-item.link {\r\n padding: 7px 0;\r\n gap: 10px;\r\n font-size: 0.9375rem;\r\n color: var(--st-nav-color, var(--st-color-text));\r\n }\r\n\r\n .menu-item.link:hover,\r\n .menu-item.link:focus-visible {\r\n padding-left: 0;\r\n background: transparent;\r\n color: var(--st-nav-color, var(--st-color-text-strong));\r\n }\r\n\r\n .menu-item.link:hover .menu-item-title,\r\n .menu-item.link:focus-visible .menu-item-title {\r\n text-decoration: underline;\r\n text-underline-offset: 4px;\r\n }\r\n\r\n .menu-item.link:active {\r\n transform: none;\r\n }\r\n\r\n .menu-item.link.active {\r\n border-left: 0;\r\n background: transparent;\r\n font-weight: 600;\r\n }\r\n\r\n .menu-item.link .menu-item-header {\r\n justify-content: flex-start;\r\n }\r\n\r\n .menu-item.link .menu-item-title {\r\n white-space: normal;\r\n font-weight: 400;\r\n }\r\n\r\n .menu-item.link .menu-item-description {\r\n margin-top: 2px;\r\n font-size: 0.8125rem;\r\n }\r\n\r\n /* bar: a top-level item in a header bar next to mega st-dropdowns (e.g. \"Dashboard\" beside\r\n \"Masters ▼\") — the same pill, size and active look as their triggers, so the row reads as\r\n one set. Wins over compact (declared after it). */\r\n .menu-item.bar {\r\n align-items: center;\r\n min-height: 40px;\r\n padding: 12px;\r\n gap: 8px;\r\n border-radius: 9999px;\r\n white-space: nowrap;\r\n }\r\n\r\n /* Hover fills like a mega trigger opening on hover. */\r\n .menu-item.bar:hover,\r\n .menu-item.bar:focus-visible {\r\n padding-left: 12px;\r\n background: var(--st-color-accent);\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n .menu-item.bar.active {\r\n border-left: 0;\r\n }\r\n\r\n .menu-item.bar .menu-item-icon {\r\n margin-top: 0;\r\n }\r\n\r\n .menu-item.bar .menu-item-title {\r\n font-size: 0.875rem;\r\n font-weight: 400;\r\n }\r\n\r\n .external {\r\n display: inline-flex;\r\n margin-left: 3px;\r\n vertical-align: 0.05em;\r\n }\r\n\r\n .menu-item.no-description {\r\n align-items: center;\r\n }\r\n\r\n .menu-item.no-description .menu-item-icon {\r\n margin-top: 0;\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .menu-item,\r\n .menu-item-icon {\r\n transition: none;\r\n }\r\n\r\n .menu-item:active,\r\n .menu-item-icon:hover {\r\n transform: none;\r\n }\r\n\r\n .menu-item-badge,\r\n .menu-item-description {\r\n animation: none;\r\n }\r\n }\r\n `;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n @property({ type: String })\r\n href = '';\r\n\r\n @property({ type: String })\r\n description = '';\r\n\r\n /** Small trailing label, e.g. a count or \"New\"/\"Beta\" — omit for none. */\r\n @property({ type: String })\r\n badge = '';\r\n\r\n /** Highlights this row as the current page (source: `isActive`). */\r\n @property({ type: Boolean, reflect: true })\r\n active = false;\r\n\r\n @property({ type: Boolean, reflect: true })\r\n compact = false;\r\n\r\n /** Suppresses the description even when `description` is set (source: `showDescription`, default `true`). */\r\n @property({ type: Boolean, attribute: 'show-description' })\r\n showDescription = true;\r\n\r\n /** `target` for the `<a>` (source default `_self`). */\r\n @property({ type: String })\r\n target = '_self';\r\n\r\n /** `default` (a row with a hover box), `link` (a plain text link, as in `st-mega-menu-column`;\r\n * marked with an arrow when it opens a new tab) or `bar` (a top-level item in a header bar,\r\n * shaped like a mega `st-dropdown`'s trigger pill so it lines up with the dropdowns beside it). */\r\n @property({ type: String, reflect: true })\r\n variant: 'default' | 'link' | 'bar' = 'default';\r\n\r\n /** Whether `slot=\"icon\"` has content, so an omitted icon leaves no empty box. */\r\n @state() private hasIcon = false;\r\n\r\n private onIconSlotChange = (event: Event): void => {\r\n this.hasIcon = (event.target as HTMLSlotElement).assignedNodes({ flatten: true }).length > 0;\r\n };\r\n\r\n private onClick = (event: MouseEvent): void => {\r\n const selectEvent = new CustomEvent<MenuItemSelectEventDetail>('menu-item-select', {\r\n detail: { href: this.href },\r\n bubbles: true,\r\n composed: true,\r\n cancelable: true\r\n });\r\n this.dispatchEvent(selectEvent);\r\n if (selectEvent.defaultPrevented) event.preventDefault();\r\n };\r\n\r\n render() {\r\n const showDescription = !!this.description && this.showDescription;\r\n const link = this.variant === 'link';\r\n const classes = [\r\n 'menu-item',\r\n link ? 'link' : '',\r\n this.variant === 'bar' ? 'bar' : '',\r\n this.active ? 'active' : '',\r\n this.compact ? 'compact' : '',\r\n showDescription ? '' : 'no-description'\r\n ]\r\n .filter(Boolean)\r\n .join(' ');\r\n const external = link && this.target === '_blank';\r\n return html`\r\n <a\r\n part=\"item\"\r\n class=${classes}\r\n href=${this.href}\r\n target=${this.target}\r\n rel=${this.target === '_blank' ? 'noopener noreferrer' : nothing}\r\n @click=${this.onClick}\r\n >\r\n <span class=\"menu-item-icon\" part=\"icon\" ?hidden=${!this.hasIcon}><slot name=\"icon\" @slotchange=${this.onIconSlotChange}></slot></span>\r\n <span class=\"menu-item-content\" part=\"content\">\r\n <span class=\"menu-item-header\" part=\"header\">\r\n <span part=\"title\" class=\"menu-item-title\"\r\n >${this.title}${external ? html`<span class=\"external\">${arrowUpRightIcon(11)}</span>` : nothing}</span\r\n >\r\n ${this.badge ? html`<span part=\"badge\" class=\"menu-item-badge\">${this.badge}</span>` : nothing}\r\n </span>\r\n ${showDescription ? html`<p part=\"description\" class=\"menu-item-description\">${this.description}</p>` : nothing}\r\n </span>\r\n </a>\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/items-accordion/ItemsAccordion.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property, state } from 'lit/decorators.js';\r\nimport 'iconify-icon';\r\n\r\nimport { buttonResetStyles, controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport {\r\n reducedMotionStyles,\r\n sectionHeaderStyles,\r\n sectionSubtitleStyles,\r\n sectionTitleStyles,\r\n} from '../shared/section-styles';\r\nimport type { AccordionToggleEventDetail } from './ItemsAccordionEvents';\r\n\r\nexport interface AccordionItem {\r\n id: string;\r\n title: string;\r\n content: string;\r\n}\r\n\r\n/**\r\n * A vertical list of collapsible title/content rows; one open at a time unless `allow-multiple`.\r\n *\r\n * @cssprop --st-items-accordion-padding - Overrides the block's padding.\r\n */\r\n@customElement('st-items-accordion')\r\nexport class ItemsAccordion extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n /* !important: a page-level reset (e.g. Tailwind Preflight) otherwise zeroes a shadow host's\r\n padding; override with --st-items-accordion-padding instead. */\r\n padding: var(--st-items-accordion-padding, var(--st-cms-section-padding) var(--st-space-24)) !important;\r\n background: var(--st-color-page);\r\n ${fontFamilyStyles}\r\n }\r\n\r\n .container {\r\n max-width: 800px;\r\n margin: 0 auto;\r\n }\r\n\r\n .header {\r\n ${sectionHeaderStyles}\r\n }\r\n\r\n .title {\r\n ${sectionTitleStyles}\r\n font-size: var(--st-text-2xl);\r\n margin-bottom: var(--st-space-12);\r\n }\r\n\r\n .subtitle {\r\n ${sectionSubtitleStyles}\r\n font-size: var(--st-text-base);\r\n margin: 0;\r\n }\r\n\r\n .list {\r\n display: flex;\r\n flex-direction: column;\r\n gap: var(--st-space-16);\r\n }\r\n\r\n .item {\r\n border: 1px solid var(--st-color-border);\r\n border-radius: var(--st-radius-lg);\r\n background: var(--st-color-surface);\r\n overflow: hidden;\r\n transition:\r\n border-color 0.2s ease,\r\n box-shadow 0.2s ease;\r\n }\r\n\r\n .item.open {\r\n border-color: var(--st-color-border-strong);\r\n box-shadow: 0 4px 6px -1px var(--st-shadow-color-sm);\r\n }\r\n\r\n .trigger {\r\n ${buttonResetStyles}\r\n width: 100%;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: var(--st-space-24);\r\n text-align: left;\r\n font-size: var(--st-text-lg);\r\n font-weight: var(--st-font-weight-semibold);\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n .trigger:hover {\r\n background: var(--st-color-hover);\r\n }\r\n\r\n .chevron {\r\n flex-shrink: 0;\r\n margin-left: var(--st-space-16);\r\n font-size: 24px;\r\n color: var(--st-color-text-faint);\r\n transition: transform 0.3s ease;\r\n }\r\n\r\n .open .chevron {\r\n transform: rotate(180deg);\r\n }\r\n\r\n .content {\r\n display: grid;\r\n grid-template-rows: 0fr;\r\n transition: grid-template-rows 0.3s ease;\r\n }\r\n\r\n .open .content {\r\n grid-template-rows: 1fr;\r\n }\r\n\r\n .content-clip {\r\n overflow: hidden;\r\n min-height: 0;\r\n }\r\n\r\n .content-inner {\r\n padding: 0 var(--st-space-24) var(--st-space-24);\r\n color: var(--st-color-text);\r\n line-height: 1.6;\r\n }\r\n\r\n @media (max-width: 768px) {\r\n :host {\r\n padding: var(--st-items-accordion-padding, var(--st-space-48) var(--st-space-20)) !important;\r\n }\r\n\r\n .title {\r\n font-size: var(--st-text-xl);\r\n }\r\n }\r\n\r\n ${reducedMotionStyles}\r\n `;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n @property({ type: String })\r\n subtitle = '';\r\n\r\n @property({ attribute: false })\r\n items: AccordionItem[] = [];\r\n\r\n @property({ type: Boolean, attribute: 'allow-multiple' })\r\n allowMultiple = false;\r\n\r\n @state() private openIds = new Set<string>();\r\n\r\n private toggle(id: string) {\r\n const wasOpen = this.openIds.has(id);\r\n const next = new Set(this.allowMultiple ? this.openIds : []);\r\n if (wasOpen) next.delete(id);\r\n else next.add(id);\r\n this.openIds = next;\r\n this.dispatchEvent(\r\n new CustomEvent<AccordionToggleEventDetail>('accordion-toggle', {\r\n detail: { id, open: !wasOpen },\r\n bubbles: true,\r\n composed: true,\r\n }),\r\n );\r\n }\r\n\r\n render() {\r\n return html`\r\n <div class=\"container\" part=\"container\">\r\n ${this.title || this.subtitle\r\n ? html`<div class=\"header\" part=\"header\">\r\n ${this.title ? html`<h2 class=\"title\" part=\"title\">${this.title}</h2>` : nothing}\r\n ${this.subtitle ? html`<p class=\"subtitle\" part=\"subtitle\">${this.subtitle}</p>` : nothing}\r\n </div>`\r\n : nothing}\r\n <div class=\"list\" part=\"list\">\r\n ${this.items.map((item) => {\r\n const open = this.openIds.has(item.id);\r\n return html`\r\n <div class=\"item ${open ? 'open' : ''}\" part=\"item\">\r\n <button\r\n class=\"trigger\"\r\n part=\"trigger\"\r\n type=\"button\"\r\n aria-expanded=${open ? 'true' : 'false'}\r\n aria-controls=\"content-${item.id}\"\r\n @click=${() => this.toggle(item.id)}\r\n >\r\n <span>${item.title}</span>\r\n <iconify-icon class=\"chevron\" icon=\"mdi:chevron-down\"></iconify-icon>\r\n </button>\r\n <div class=\"content\" id=\"content-${item.id}\" part=\"content\" role=\"region\" ?inert=${!open}>\r\n <div class=\"content-clip\">\r\n <div class=\"content-inner\">${item.content}</div>\r\n </div>\r\n </div>\r\n </div>\r\n `;\r\n })}\r\n </div>\r\n </div>\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/promo-banner/PromoBanner.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\n\r\nimport { buttonResetStyles, controlBaseStyles, rootFontFamilyStyles } from '../shared/styles';\r\nimport { ctaLinkStyles, sectionSubtitleStyles, sectionTitleStyles } from '../shared/section-styles';\r\nimport type { HeroActionEventDetail } from '../hero/HeroEvents';\r\n\r\n/**\r\n * Rounded call-to-action banner (title, subtitle, one outlined button) on a dark panel or a\r\n * background image. Port of `SankhyaUI`'s React `PromoBanner`; the button fires an `action` event\r\n * (detail `{ href }`, empty unless set) in place of `onAction`.\r\n *\r\n * @cssprop --st-promo-banner-margin - Overrides the banner's margin.\r\n * @cssprop --st-promo-banner-padding - Overrides the banner's padding.\r\n */\r\n@customElement('st-promo-banner')\r\nexport class PromoBanner extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n box-sizing: border-box;\r\n width: calc(100% - 48px);\r\n max-width: var(--st-cms-container-max);\r\n /* !important: a page-level reset (e.g. Tailwind Preflight) otherwise zeroes a shadow host's\r\n margin/padding; override with --st-promo-banner-margin/-padding instead. */\r\n margin: var(--st-promo-banner-margin, var(--st-space-40) auto) !important;\r\n padding: var(--st-promo-banner-padding, 100px var(--st-space-24)) !important;\r\n border-radius: var(--st-space-24);\r\n background-color: var(--st-color-text-strong);\r\n background-size: cover;\r\n background-position: center;\r\n color: var(--st-color-on-solid);\r\n text-align: center;\r\n ${rootFontFamilyStyles}\r\n }\r\n\r\n :host([inverted]) {\r\n background-color: var(--st-color-subtle);\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n .container {\r\n max-width: 800px;\r\n margin: 0 auto;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n gap: var(--st-space-32);\r\n }\r\n\r\n .title {\r\n ${sectionTitleStyles}\r\n color: inherit;\r\n margin: 0;\r\n letter-spacing: -0.02em;\r\n }\r\n\r\n .subtitle {\r\n ${sectionSubtitleStyles}\r\n color: inherit;\r\n opacity: 0.8;\r\n margin: 0;\r\n }\r\n\r\n .actions {\r\n margin-top: var(--st-space-16);\r\n }\r\n\r\n .cta {\r\n ${buttonResetStyles}\r\n ${ctaLinkStyles}\r\n border: 1px solid currentColor;\r\n color: inherit;\r\n }\r\n\r\n .cta:hover {\r\n transform: scale(1.05);\r\n }\r\n\r\n @media (max-width: 768px) {\r\n :host {\r\n width: auto;\r\n margin: var(--st-promo-banner-margin, var(--st-space-24)) !important;\r\n padding: var(--st-promo-banner-padding, 60px var(--st-space-24)) !important;\r\n border-radius: var(--st-radius-lg);\r\n }\r\n .actions,\r\n .cta {\r\n width: 100%;\r\n }\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .cta {\r\n transition: none;\r\n }\r\n }\r\n `;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n @property({ type: String })\r\n subtitle = '';\r\n\r\n @property({ type: String, attribute: 'action-label' })\r\n actionLabel = '';\r\n\r\n @property({ type: String })\r\n href = '';\r\n\r\n @property({ type: String, attribute: 'image-src' })\r\n imageSrc = '';\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n protected willUpdate(): void {\r\n this.style.backgroundImage = this.imageSrc ? `url(${JSON.stringify(this.imageSrc)})` : '';\r\n }\r\n\r\n private onAction = (): void => {\r\n this.dispatchEvent(\r\n new CustomEvent<HeroActionEventDetail>('action', { detail: { href: this.href }, bubbles: true, composed: true })\r\n );\r\n };\r\n\r\n render() {\r\n return html`\r\n <div class=\"container\" part=\"container\">\r\n <h2 class=\"title\" part=\"title\">${this.title}</h2>\r\n ${this.subtitle ? html`<p class=\"subtitle\" part=\"subtitle\">${this.subtitle}</p>` : nothing}\r\n <slot></slot>\r\n ${this.actionLabel\r\n ? html`<div class=\"actions\" part=\"actions\">\r\n <button class=\"cta\" part=\"action\" type=\"button\" @click=${this.onAction}>${this.actionLabel}</button>\r\n </div>`\r\n : nothing}\r\n </div>\r\n `;\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;AAAA,SAAS,YAAY,KAAK,MAAM,eAAe;AAC/C,SAAS,eAAe,gBAAgB;AAejC,IAAM,cAAN,cAA0B,WAAW;AAAA,EAArC;AAAA;AAsFL,iBAAQ;AAGR,oBAAW;AAGX,uBAAc;AAGd,gBAAO;AAGP,oBAAW;AAGX,oBAAW;AAMX,SAAQ,WAAW,MAAY;AAC7B,WAAK;AAAA,QACH,IAAI,YAAmC,UAAU,EAAE,QAAQ,EAAE,MAAM,KAAK,KAAK,GAAG,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,MACjH;AAAA,IACF;AAAA;AAAA,EARU,aAAmB;AAC3B,SAAK,MAAM,kBAAkB,KAAK,WAAW,OAAO,KAAK,UAAU,KAAK,QAAQ,CAAC,MAAM;AAAA,EACzF;AAAA,EAQA,SAAS;AACP,WAAO;AAAA;AAAA,yCAE8B,KAAK,KAAK;AAAA,UACzC,KAAK,WAAW,2CAA2C,KAAK,QAAQ,SAAS,OAAO;AAAA;AAAA,UAExF,KAAK,cACH;AAAA,uEAC2D,KAAK,QAAQ,IAAI,KAAK,WAAW;AAAA,sBAE5F,OAAO;AAAA;AAAA;AAAA,EAGjB;AACF;AA/Ha,YACJ,SAAS;AAAA,MACZ,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAiBf,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAkBpB,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOlB,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAWrB,iBAAiB;AAAA,QACjB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8BnB;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GArFf,YAsFX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAxFf,YAyFX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,eAAe,CAAC;AAAA,GA3F1C,YA4FX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GA9Ff,YA+FX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,YAAY,CAAC;AAAA,GAjGvC,YAkGX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GApG/B,YAqGX;AArGW,cAAN;AAAA,EADN,cAAc,iBAAiB;AAAA,GACnB;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/dropdown/Dropdown.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property, state } from 'lit/decorators.js';\r\n\r\nimport { chevronIcon } from '../shared/icons';\r\nimport { buttonResetStyles, controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport type { DropdownToggleEventDetail } from './DropdownEvents';\r\n\r\n/**\r\n * A labeled trigger + slotted dropdown panel — nav menus (typically holding an `st-menu-grid`),\r\n * action menus, anything \"click a trigger, show content under it\". A 1:1 port of `SankhyaUI`'s\r\n * React `Dropdown` (`SankhyaCMS/SankhyaUI/src/components/Dropdown`): same markup\r\n * (`.menu` > `.menu-title` + `.menu-dropdown`), sizes, 0.3s slide/fade, and behavior —\r\n *\r\n * - only one dropdown is open at a time (the source's `DropdownProvider`, built in here, so no\r\n * provider element is needed);\r\n * - a mousedown outside, Escape, or a click inside the panel closes it;\r\n * - an `href` trigger toggles the panel when it has content, and is a plain link when it doesn't;\r\n * - `inline` opens the panel in the flow, the source's `.touch-device` layout.\r\n *\r\n * Colors and the panel's surface come from the suite theme (the source left those to the\r\n * consumer's `className`/`itemGroupClassName` utility classes). Two source rules are left out\r\n * because they break existing suite uses (`st-source-bar`'s site/library menus): the 100vw panel\r\n * at <=768px (overflows the screen from wherever the trigger sits; the header uses `inline`\r\n * instead) and `overflow: hidden` on slotted children (clips their focus rings). Suite additions\r\n * kept on top: `align`, `active`, `disabled`, `inline`, and the `dropdown-toggle` event — plus\r\n * `mega` and `open-on-hover` for an okta.com-style mega menu (see `st-mega-menu`).\r\n *\r\n * @cssprop --st-mega-menu-max-width - Maximum width of a `mega` panel (default `1400px`).\r\n * @cssprop --st-mega-menu-inset - Minimum space between a `mega` panel and the header's sides (default `1rem`).\r\n * @cssprop --st-mega-menu-gap - Space between the header and a `mega` panel (default `12px`).\r\n * @cssprop --st-mega-menu-radius - Corner radius of a `mega` panel (default `24px`).\r\n */\r\n@customElement('st-dropdown')\r\nexport class Dropdown extends LitElement {\r\n /** The open dropdown, if any — the source's `DropdownContext.activeDropdown`. */\r\n private static openDropdown: Dropdown | null = null;\r\n\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: inline-block;\r\n position: relative;\r\n ${fontFamilyStyles}\r\n }\r\n\r\n .menu-title {\r\n ${buttonResetStyles}\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n box-sizing: border-box;\r\n min-height: 40px;\r\n padding: 12px;\r\n gap: 8px;\r\n text-align: center;\r\n width: fit-content;\r\n border-radius: var(--st-radius-sm);\r\n /* --st-nav-*: set by a host bar (st-header's transparent state) to recolour its nav items. */\r\n color: var(--st-nav-color, var(--st-color-text));\r\n font-size: 0.875rem;\r\n text-decoration: none;\r\n white-space: nowrap;\r\n transition: background-color 0.3s ease;\r\n }\r\n\r\n .menu-title:hover,\r\n .menu-title[aria-expanded='true'] {\r\n background: var(--st-nav-hover-bg, var(--st-color-hover));\r\n color: var(--st-nav-color, var(--st-color-text-strong));\r\n }\r\n\r\n :host([active]) .menu-title {\r\n background: var(--st-color-accent-subtle);\r\n color: var(--st-color-accent-text);\r\n }\r\n\r\n :host([disabled]) .menu-title {\r\n color: var(--st-color-text-muted);\r\n cursor: not-allowed;\r\n pointer-events: none;\r\n }\r\n\r\n .icon {\r\n display: inline-flex;\r\n flex: none;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n\r\n .icon[hidden] {\r\n display: none;\r\n }\r\n\r\n .arrow {\r\n display: inline-block;\r\n margin-left: 8px;\r\n font-size: 0.75rem;\r\n transition: transform 0.3s ease;\r\n }\r\n\r\n .menu-title[aria-expanded='true'] .arrow {\r\n transform: rotate(180deg);\r\n }\r\n\r\n .menu-dropdown {\r\n position: absolute;\r\n top: 100%;\r\n left: 0;\r\n z-index: 100;\r\n padding: 16px;\r\n background: var(--st-color-surface);\r\n color: var(--st-color-text);\r\n /* The panel has its own surface: items in it never take the bar's nav colours. */\r\n --st-nav-color: initial;\r\n --st-nav-hover-bg: initial;\r\n border: 1px solid var(--st-color-border);\r\n border-radius: var(--st-radius-sm);\r\n box-shadow: 0 4px 16px var(--st-shadow-color-sm);\r\n opacity: 0;\r\n visibility: hidden;\r\n transform: translateY(-10px);\r\n /* visibility flips at once on open (so keyboard focus can move into the panel on the same\r\n frame) and only after the 0.3s fade on close. */\r\n transition:\r\n opacity 0.3s ease,\r\n transform 0.3s ease,\r\n visibility 0s linear 0.3s;\r\n pointer-events: none;\r\n }\r\n\r\n .menu-dropdown.align-right {\r\n left: auto;\r\n right: 0;\r\n }\r\n\r\n .menu-dropdown.show {\r\n opacity: 1;\r\n visibility: visible;\r\n transform: translateY(0);\r\n pointer-events: auto;\r\n transition-delay: 0s;\r\n }\r\n\r\n /* Inline: the panel opens in the flow under its trigger and pushes what follows down, instead\r\n of floating — the source's .touch-device layout. st-header turns this on for its menu while\r\n the hamburger panel is showing. */\r\n :host([inline]) {\r\n display: block;\r\n }\r\n\r\n :host([inline]) .menu-title {\r\n width: 100%;\r\n justify-content: flex-start;\r\n }\r\n\r\n :host([inline]) .arrow {\r\n margin-left: auto;\r\n }\r\n\r\n :host([inline]) .menu-dropdown {\r\n display: none;\r\n position: relative;\r\n top: auto;\r\n left: auto;\r\n right: auto;\r\n width: 100%;\r\n box-sizing: border-box;\r\n box-shadow: none;\r\n opacity: 1;\r\n visibility: visible;\r\n transform: none;\r\n }\r\n\r\n :host([inline]) .menu-dropdown.show {\r\n display: block;\r\n pointer-events: auto;\r\n }\r\n\r\n /* Mega (okta.com): the panel is a large rounded card floating under the whole bar, centred on\r\n the nearest positioned ancestor (st-header) instead of hanging off the trigger — the host\r\n stops being the panel's containing block. */\r\n :host([mega]:not([inline])) {\r\n position: static;\r\n }\r\n\r\n :host([mega]:not([inline])) .menu-dropdown {\r\n top: calc(100% + var(--st-mega-menu-gap, 12px));\r\n left: var(--st-mega-menu-inset, 1rem);\r\n right: var(--st-mega-menu-inset, 1rem);\r\n max-width: var(--st-mega-menu-max-width, 1400px);\r\n margin: 0 auto;\r\n padding: 0;\r\n max-height: calc(100dvh - var(--st-mega-menu-offset, 96px));\r\n overflow-y: auto;\r\n border: 0;\r\n border-radius: var(--st-mega-menu-radius, 24px);\r\n box-shadow: 0 24px 48px var(--st-shadow-color-md);\r\n }\r\n\r\n /* The open section's trigger becomes an accent pill — also for a plain dropdown marked \\`bar\\`,\r\n so it matches the mega triggers (and st-menu-item variant=\"bar\") beside it. */\r\n :host([mega]:not([inline])) .menu-title,\r\n :host([bar]:not([inline])) .menu-title {\r\n border-radius: 9999px;\r\n }\r\n\r\n :host([mega]:not([inline])) .menu-title[aria-expanded='true'],\r\n :host([bar]:not([inline])) .menu-title[aria-expanded='true'] {\r\n background: var(--st-color-accent);\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n .mega-back-bar,\r\n .mega-heading {\r\n display: none;\r\n }\r\n\r\n /* Mega in st-header's hamburger panel: rather than an accordion, the panel slides in over the\r\n whole screen with a Back button (okta.com's phone menu). Fixed to the viewport, stacked\r\n inside the header's own full-screen layer, so the header's close toggle stays on top. */\r\n :host([mega][inline]) .menu-dropdown {\r\n display: block;\r\n position: fixed;\r\n inset: 0;\r\n z-index: 1;\r\n padding: 0 1.5rem 2rem;\r\n overflow-y: auto;\r\n border: 0;\r\n border-radius: 0;\r\n visibility: hidden;\r\n transform: translateX(100%);\r\n transition:\r\n transform 0.3s ease,\r\n visibility 0s linear 0.3s;\r\n }\r\n\r\n :host([mega][inline]) .menu-dropdown.show {\r\n visibility: visible;\r\n transform: none;\r\n transition-delay: 0s;\r\n }\r\n\r\n :host([mega][inline]) .mega-back-bar {\r\n display: flex;\r\n align-items: center;\r\n position: sticky;\r\n top: 0;\r\n z-index: 1;\r\n height: 64px;\r\n margin: 0 -1.5rem;\r\n padding: 0 1rem;\r\n background: inherit;\r\n border-bottom: 1px solid var(--st-color-border);\r\n }\r\n\r\n .mega-back {\r\n ${buttonResetStyles}\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 6px;\r\n height: 40px;\r\n padding: 0 12px 0 6px;\r\n border-radius: var(--st-radius-sm);\r\n font-size: 0.875rem;\r\n font-weight: 600;\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n .mega-back:hover {\r\n background: var(--st-color-hover);\r\n }\r\n\r\n :host([mega][inline]) .mega-heading {\r\n display: block;\r\n margin: 1.25rem 0 0.75rem;\r\n font-size: 1.375rem;\r\n font-weight: 600;\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n /* The drill-down replaces the trigger's open state, so the caret points the way it goes. */\r\n :host([mega][inline]) .arrow {\r\n transform: rotate(-90deg);\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .menu-dropdown,\r\n .arrow,\r\n :host([mega][inline]) .menu-dropdown {\r\n transition: none;\r\n }\r\n }\r\n `;\r\n\r\n /** Trigger label text (source: `title`, renamed because `title` is the native tooltip\r\n * attribute). Leave empty to show only `slot=\"icon\"`. */\r\n @property({ type: String })\r\n label = '';\r\n\r\n /** Renders the trigger as an `<a href>`. With panel content the click toggles the panel (as in\r\n * the source); with none it navigates. */\r\n @property({ type: String })\r\n href = '';\r\n\r\n @property({ type: String, attribute: 'icon-position' })\r\n iconPosition: 'left' | 'right' = 'left';\r\n\r\n /** Inline `width`/`height` of the `slot=\"icon\"` wrapper (source: `iconSize`, default `1.2rem`). */\r\n @property({ type: String, attribute: 'icon-size' })\r\n iconSize = '1.2rem';\r\n\r\n /** Inline `color` of the `slot=\"icon\"` wrapper (source: `iconColor`). */\r\n @property({ type: String, attribute: 'icon-color' })\r\n iconColor = 'currentColor';\r\n\r\n /** Which edge of the trigger the panel lines up with. */\r\n @property({ type: String })\r\n align: 'left' | 'right' = 'left';\r\n\r\n /** `target` of an `href` trigger (source default `_self`). */\r\n @property({ type: String })\r\n target = '_self';\r\n\r\n /** Extra class(es) on the trigger (source: `className`; a `class` on `st-dropdown` styles the host). */\r\n @property({ type: String, attribute: 'trigger-class-name' })\r\n triggerClassName = '';\r\n\r\n /** Extra class(es) on the panel (source: `itemGroupClassName`). */\r\n @property({ type: String, attribute: 'item-group-class-name' })\r\n itemGroupClassName = '';\r\n\r\n /** Unused, as in the source (`itemClassName` is never read there); kept for prop parity. */\r\n @property({ type: String, attribute: 'item-class-name' })\r\n itemClassName = '';\r\n\r\n @property({ type: Boolean, reflect: true })\r\n disabled = false;\r\n\r\n /** Highlights the trigger as the current section (e.g. the current page is one of its items). */\r\n @property({ type: Boolean, reflect: true })\r\n active = false;\r\n\r\n /** Opens the panel in the flow under the trigger instead of floating over the page (see the\r\n * styles). `st-header` sets this on its own menu's dropdowns while its hamburger panel shows. */\r\n @property({ type: Boolean, reflect: true })\r\n inline = false;\r\n\r\n /** Whether the panel is showing. Follows user toggles; may also be set from outside. */\r\n @property({ type: Boolean, reflect: true })\r\n open = false;\r\n\r\n /**\r\n * Mega-menu panel (okta.com style), typically holding an `st-mega-menu`: the panel spans the\r\n * full width of the nearest positioned ancestor — `st-header` — right under it, instead of\r\n * hanging off the trigger. In `st-header`'s hamburger layout (`inline`) it slides in over the\r\n * screen with a Back button rather than opening as an accordion. A click inside the panel only\r\n * closes it when it lands on a link.\r\n */\r\n @property({ type: Boolean, reflect: true })\r\n mega = false;\r\n\r\n /** Styles a non-`mega` trigger like a mega one — a pill that turns solid accent while open — so\r\n * a plain dropdown (e.g. \"+ New\") lines up with mega triggers in the same header bar. */\r\n @property({ type: Boolean, reflect: true })\r\n bar = false;\r\n\r\n /** Opens the panel while a mouse hovers the trigger or panel (touch and keyboard still click). Off while `inline`. */\r\n @property({ type: Boolean, attribute: 'open-on-hover' })\r\n openOnHover = false;\r\n\r\n /** Text of the Back button in the `mega` + `inline` drill-down panel. */\r\n @property({ type: String, attribute: 'back-label' })\r\n backLabel = 'Back';\r\n\r\n private hoverTimer = 0;\r\n\r\n /** When hover last opened the panel — a click right after that keeps it open instead of toggling it shut. */\r\n private hoverOpenedAt = 0;\r\n\r\n /** Whether the default slot has content — the source's `children` check. */\r\n @state() private hasContent = false;\r\n\r\n /** Whether `slot=\"icon\"` has content. */\r\n @state() private hasIcon = false;\r\n\r\n connectedCallback(): void {\r\n super.connectedCallback();\r\n document.addEventListener('mousedown', this.closeOnOutsideMouseDown);\r\n window.addEventListener('keydown', this.closeOnEscape);\r\n this.addEventListener('pointerenter', this.onPointerEnter);\r\n this.addEventListener('pointerleave', this.onPointerLeave);\r\n }\r\n\r\n disconnectedCallback(): void {\r\n document.removeEventListener('mousedown', this.closeOnOutsideMouseDown);\r\n window.removeEventListener('keydown', this.closeOnEscape);\r\n this.removeEventListener('pointerenter', this.onPointerEnter);\r\n this.removeEventListener('pointerleave', this.onPointerLeave);\r\n clearTimeout(this.hoverTimer);\r\n if (Dropdown.openDropdown === this) Dropdown.openDropdown = null;\r\n super.disconnectedCallback();\r\n }\r\n\r\n protected updated(changed: Map<string, unknown>): void {\r\n if (!changed.has('open')) return;\r\n if (this.open) {\r\n const previous = Dropdown.openDropdown;\r\n Dropdown.openDropdown = this;\r\n if (previous && previous !== this) previous.setOpen(false);\r\n } else if (Dropdown.openDropdown === this) {\r\n Dropdown.openDropdown = null;\r\n }\r\n }\r\n\r\n private setOpen(open: boolean): void {\r\n if (this.open === open) return;\r\n this.open = open;\r\n this.dispatchEvent(new CustomEvent<DropdownToggleEventDetail>('dropdown-toggle', { detail: { open }, bubbles: true, composed: true }));\r\n }\r\n\r\n private hovers(event: PointerEvent): boolean {\r\n return this.openOnHover && !this.inline && !this.disabled && this.hasContent && event.pointerType === 'mouse';\r\n }\r\n\r\n /** Short delays so a pointer crossing the gap between trigger and panel doesn't close it. */\r\n private onPointerEnter = (event: PointerEvent): void => {\r\n if (!this.hovers(event)) return;\r\n clearTimeout(this.hoverTimer);\r\n this.hoverTimer = window.setTimeout(() => {\r\n if (!this.open) this.hoverOpenedAt = Date.now();\r\n this.setOpen(true);\r\n }, 80);\r\n };\r\n\r\n private onPointerLeave = (event: PointerEvent): void => {\r\n if (!this.hovers(event)) return;\r\n clearTimeout(this.hoverTimer);\r\n this.hoverTimer = window.setTimeout(() => this.setOpen(false), 200);\r\n };\r\n\r\n private onBackClick = (event: Event): void => {\r\n event.stopPropagation();\r\n this.setOpen(false);\r\n this.trigger()?.focus();\r\n };\r\n\r\n private closeOnOutsideMouseDown = (event: Event): void => {\r\n if (this.open && !event.composedPath().includes(this)) this.setOpen(false);\r\n };\r\n\r\n private closeOnEscape = (event: KeyboardEvent): void => {\r\n if (!this.open || event.key !== 'Escape') return;\r\n const focusWasInside = event.composedPath().includes(this);\r\n this.setOpen(false);\r\n if (focusWasInside) this.trigger()?.focus();\r\n };\r\n\r\n private trigger(): HTMLElement | null {\r\n return this.renderRoot.querySelector<HTMLElement>('.menu-title');\r\n }\r\n\r\n /** Keyboard-reachable entries in the panel, in order: menu items (they delegate focus to their\r\n * own link) plus any plain links/buttons/tabbable elements a caller slots in. */\r\n private panelItems(): HTMLElement[] {\r\n const slot = this.renderRoot.querySelector<HTMLSlotElement>('.menu-dropdown slot');\r\n if (!slot) return [];\r\n const selector =\r\n 'st-menu-item, st-menu-grid-item, st-mega-menu-feature, a[href], button:not([disabled]), input:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\r\n const items: HTMLElement[] = [];\r\n for (const el of slot.assignedElements({ flatten: true })) {\r\n if (el.matches(selector)) items.push(el as HTMLElement);\r\n items.push(...Array.from(el.querySelectorAll<HTMLElement>(selector)));\r\n }\r\n return items;\r\n }\r\n\r\n /** Moves focus into the panel once it has become visible (it is `visibility: hidden` until the\r\n * `show` class lands, and hidden elements can't take focus). */\r\n private focusItem(pick: (items: HTMLElement[]) => HTMLElement | undefined): void {\r\n void this.updateComplete.then(() => pick(this.panelItems())?.focus());\r\n }\r\n\r\n /** Enter/Space/ArrowDown open the panel and focus its first entry; ArrowUp its last. */\r\n private onTitleKeyDown = (event: KeyboardEvent): void => {\r\n if (!this.hasContent || this.disabled) return;\r\n if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.setOpen(true);\r\n this.focusItem((items) => items[0]);\r\n } else if (event.key === 'ArrowUp') {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.setOpen(true);\r\n this.focusItem((items) => items[items.length - 1]);\r\n }\r\n };\r\n\r\n /** Arrow keys/Home/End move between the panel's entries; Tab closes the panel and moves on. */\r\n private onPanelKeyDown = (event: KeyboardEvent): void => {\r\n if (event.key === 'Tab') {\r\n this.setOpen(false);\r\n return;\r\n }\r\n if (!['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) return;\r\n const items = this.panelItems();\r\n if (items.length === 0) return;\r\n event.preventDefault();\r\n event.stopPropagation();\r\n const path = event.composedPath();\r\n const current = items.findIndex((item) => path.includes(item));\r\n const last = items.length - 1;\r\n const next =\r\n event.key === 'Home'\r\n ? 0\r\n : event.key === 'End'\r\n ? last\r\n : event.key === 'ArrowDown'\r\n ? current < 0 || current === last ? 0 : current + 1\r\n : current <= 0 ? last : current - 1;\r\n items[next].focus();\r\n };\r\n\r\n private onTitleClick = (event: Event): void => {\r\n event.stopPropagation();\r\n if (!this.hasContent) return;\r\n event.preventDefault();\r\n clearTimeout(this.hoverTimer);\r\n if (this.open && Date.now() - this.hoverOpenedAt < 400) return;\r\n this.setOpen(!this.open);\r\n };\r\n\r\n /** A click anywhere inside the panel closes it, as in the source — for `mega`, only a click on a\r\n * link: a big panel has headings and gaps, and a click there shouldn't also close st-header's\r\n * hamburger layer. */\r\n private onPanelClick = (event: Event): void => {\r\n if (this.mega && !event.composedPath().some((node) => node instanceof HTMLAnchorElement)) {\r\n event.stopPropagation();\r\n return;\r\n }\r\n this.setOpen(false);\r\n };\r\n\r\n private onContentSlotChange = (event: Event): void => {\r\n this.hasContent = (event.target as HTMLSlotElement).assignedNodes({ flatten: true }).some(\r\n (node) => node.nodeType === Node.ELEMENT_NODE || !!node.textContent?.trim()\r\n );\r\n };\r\n\r\n private onIconSlotChange = (event: Event): void => {\r\n this.hasIcon = (event.target as HTMLSlotElement).assignedNodes({ flatten: true }).length > 0;\r\n };\r\n\r\n render() {\r\n const icon = html`<span\r\n class=\"icon ${this.iconPosition === 'left' ? 'icon-left' : 'icon-right'}\"\r\n ?hidden=${!this.hasIcon}\r\n style=\"width:${this.iconSize};height:${this.iconSize};color:${this.iconColor}\"\r\n ><slot name=\"icon\" @slotchange=${this.onIconSlotChange}></slot\r\n ></span>`;\r\n const titleContent = html`\r\n ${this.iconPosition === 'left' ? icon : nothing} ${this.label ? html`<span part=\"label\">${this.label}</span>` : nothing}\r\n ${this.iconPosition === 'right' ? icon : nothing}\r\n ${this.hasContent ? html`<span class=\"arrow\" part=\"caret\" aria-hidden=\"true\">▼</span>` : nothing}\r\n `;\r\n const titleClass = `menu-title ${this.triggerClassName} ${this.open ? 'active' : ''}`;\r\n\r\n return html`\r\n <div class=\"menu\" part=\"menu\">\r\n ${this.href\r\n ? html`\r\n <a\r\n part=\"trigger\"\r\n class=${titleClass}\r\n href=${this.href}\r\n target=${this.target}\r\n aria-haspopup=${this.hasContent ? 'true' : 'false'}\r\n aria-expanded=${this.open}\r\n aria-disabled=${this.disabled ? 'true' : nothing}\r\n @click=${this.onTitleClick}\r\n @keydown=${this.onTitleKeyDown}\r\n >\r\n ${titleContent}\r\n </a>\r\n `\r\n : html`\r\n <button\r\n part=\"trigger\"\r\n class=${titleClass}\r\n type=\"button\"\r\n aria-haspopup=\"true\"\r\n aria-expanded=${this.open}\r\n ?disabled=${this.disabled}\r\n @click=${this.onTitleClick}\r\n @keydown=${this.onTitleKeyDown}\r\n >\r\n ${titleContent}\r\n </button>\r\n `}\r\n <div\r\n part=\"panel\"\r\n class=\"menu-dropdown align-${this.align} ${this.itemGroupClassName} ${this.open ? 'show' : ''}\"\r\n role=\"menu\"\r\n @click=${this.onPanelClick}\r\n @keydown=${this.onPanelKeyDown}\r\n >\r\n ${this.mega\r\n ? html`\r\n <div class=\"mega-back-bar\" part=\"back-bar\">\r\n <button type=\"button\" class=\"mega-back\" part=\"back\" @click=${this.onBackClick}>\r\n ${chevronIcon('left', 16)} ${this.backLabel}\r\n </button>\r\n </div>\r\n ${this.label ? html`<p class=\"mega-heading\" part=\"mobile-heading\">${this.label}</p>` : nothing}\r\n `\r\n : nothing}\r\n <slot @slotchange=${this.onContentSlotChange}></slot>\r\n </div>\r\n </div>\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":[]}