@pure-ds/storybook 0.1.0

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 (129) hide show
  1. package/.storybook/addons/description/preview.js +15 -0
  2. package/.storybook/addons/description/register.js +60 -0
  3. package/.storybook/addons/html-preview/Panel.jsx +327 -0
  4. package/.storybook/addons/html-preview/constants.js +6 -0
  5. package/.storybook/addons/html-preview/preview.js +178 -0
  6. package/.storybook/addons/html-preview/register.js +16 -0
  7. package/.storybook/addons/pds-configurator/SearchTool.js +44 -0
  8. package/.storybook/addons/pds-configurator/Tool.js +30 -0
  9. package/.storybook/addons/pds-configurator/constants.js +9 -0
  10. package/.storybook/addons/pds-configurator/preview.js +159 -0
  11. package/.storybook/addons/pds-configurator/register.js +24 -0
  12. package/.storybook/docs.css +35 -0
  13. package/.storybook/htmlPreview.css +103 -0
  14. package/.storybook/htmlPreview.js +271 -0
  15. package/.storybook/main.js +160 -0
  16. package/.storybook/preview-body.html +48 -0
  17. package/.storybook/preview-head.html +11 -0
  18. package/.storybook/preview.js +1563 -0
  19. package/README.md +266 -0
  20. package/bin/index.js +40 -0
  21. package/dist/pds-reference.json +2101 -0
  22. package/package.json +45 -0
  23. package/pds.config.js +6 -0
  24. package/public/assets/css/app.css +1216 -0
  25. package/public/assets/data/auto-design-advanced.json +704 -0
  26. package/public/assets/data/auto-design-simple.json +123 -0
  27. package/public/assets/img/icon-512x512.png +0 -0
  28. package/public/assets/img/logo-trans.png +0 -0
  29. package/public/assets/img/logo.png +0 -0
  30. package/public/assets/js/app.js +15088 -0
  31. package/public/assets/js/app.js.map +7 -0
  32. package/public/assets/js/lit.js +1176 -0
  33. package/public/assets/js/lit.js.map +7 -0
  34. package/public/assets/js/pds.js +9801 -0
  35. package/public/assets/js/pds.js.map +7 -0
  36. package/public/assets/pds/components/pds-calendar.js +837 -0
  37. package/public/assets/pds/components/pds-drawer.js +857 -0
  38. package/public/assets/pds/components/pds-icon.js +338 -0
  39. package/public/assets/pds/components/pds-jsonform.js +1775 -0
  40. package/public/assets/pds/components/pds-richtext.js +1035 -0
  41. package/public/assets/pds/components/pds-scrollrow.js +331 -0
  42. package/public/assets/pds/components/pds-splitpanel.js +401 -0
  43. package/public/assets/pds/components/pds-tabstrip.js +251 -0
  44. package/public/assets/pds/components/pds-toaster.js +446 -0
  45. package/public/assets/pds/components/pds-upload.js +657 -0
  46. package/public/assets/pds/custom-elements.json +2003 -0
  47. package/public/assets/pds/icons/pds-icons.svg +498 -0
  48. package/public/assets/pds/pds-css-complete.json +1861 -0
  49. package/public/assets/pds/pds-runtime-config.json +11 -0
  50. package/public/assets/pds/pds.css-data.json +2152 -0
  51. package/public/assets/pds/styles/pds-components.css +1944 -0
  52. package/public/assets/pds/styles/pds-components.css.js +3895 -0
  53. package/public/assets/pds/styles/pds-primitives.css +352 -0
  54. package/public/assets/pds/styles/pds-primitives.css.js +711 -0
  55. package/public/assets/pds/styles/pds-styles.css +3761 -0
  56. package/public/assets/pds/styles/pds-styles.css.js +7529 -0
  57. package/public/assets/pds/styles/pds-tokens.css +699 -0
  58. package/public/assets/pds/styles/pds-tokens.css.js +1405 -0
  59. package/public/assets/pds/styles/pds-utilities.css +763 -0
  60. package/public/assets/pds/styles/pds-utilities.css.js +1533 -0
  61. package/public/assets/pds/vscode-custom-data.json +824 -0
  62. package/scripts/build-pds-reference.mjs +807 -0
  63. package/scripts/generate-stories.js +542 -0
  64. package/scripts/package-build.js +86 -0
  65. package/src/js/app.js +17 -0
  66. package/src/js/common/ask.js +208 -0
  67. package/src/js/common/common.js +20 -0
  68. package/src/js/common/font-loader.js +200 -0
  69. package/src/js/common/msg.js +90 -0
  70. package/src/js/lit.js +40 -0
  71. package/src/js/pds-core/pds-config.js +1162 -0
  72. package/src/js/pds-core/pds-enhancer-metadata.js +75 -0
  73. package/src/js/pds-core/pds-enhancers.js +357 -0
  74. package/src/js/pds-core/pds-enums.js +86 -0
  75. package/src/js/pds-core/pds-generator.js +5317 -0
  76. package/src/js/pds-core/pds-ontology.js +256 -0
  77. package/src/js/pds-core/pds-paths.js +109 -0
  78. package/src/js/pds-core/pds-query.js +571 -0
  79. package/src/js/pds-core/pds-registry.js +129 -0
  80. package/src/js/pds-core/pds.d.ts +129 -0
  81. package/src/js/pds.d.ts +408 -0
  82. package/src/js/pds.js +1579 -0
  83. package/src/pds-core/pds-api.js +105 -0
  84. package/stories/GettingStarted.md +96 -0
  85. package/stories/GettingStarted.stories.js +144 -0
  86. package/stories/WhatIsPDS.md +194 -0
  87. package/stories/WhatIsPDS.stories.js +144 -0
  88. package/stories/components/PdsCalendar.stories.js +263 -0
  89. package/stories/components/PdsDrawer.stories.js +623 -0
  90. package/stories/components/PdsIcon.stories.js +78 -0
  91. package/stories/components/PdsJsonform.stories.js +1444 -0
  92. package/stories/components/PdsRichtext.stories.js +367 -0
  93. package/stories/components/PdsScrollrow.stories.js +140 -0
  94. package/stories/components/PdsSplitpanel.stories.js +502 -0
  95. package/stories/components/PdsTabstrip.stories.js +442 -0
  96. package/stories/components/PdsToaster.stories.js +186 -0
  97. package/stories/components/PdsUpload.stories.js +66 -0
  98. package/stories/enhancements/Dropdowns.stories.js +185 -0
  99. package/stories/enhancements/InteractiveStates.stories.js +625 -0
  100. package/stories/enhancements/MeshGradients.stories.js +320 -0
  101. package/stories/enhancements/OpenGroups.stories.js +227 -0
  102. package/stories/enhancements/RangeSliders.stories.js +232 -0
  103. package/stories/enhancements/RequiredFields.stories.js +189 -0
  104. package/stories/enhancements/Toggles.stories.js +167 -0
  105. package/stories/foundations/Colors.stories.js +283 -0
  106. package/stories/foundations/Icons.stories.js +305 -0
  107. package/stories/foundations/SmartSurfaces.stories.js +367 -0
  108. package/stories/foundations/Spacing.stories.js +175 -0
  109. package/stories/foundations/Typography.stories.js +960 -0
  110. package/stories/foundations/ZIndex.stories.js +325 -0
  111. package/stories/patterns/BorderEffects.stories.js +72 -0
  112. package/stories/patterns/Layout.stories.js +99 -0
  113. package/stories/patterns/Utilities.stories.js +107 -0
  114. package/stories/primitives/Accordion.stories.js +359 -0
  115. package/stories/primitives/Alerts.stories.js +64 -0
  116. package/stories/primitives/Badges.stories.js +183 -0
  117. package/stories/primitives/Buttons.stories.js +229 -0
  118. package/stories/primitives/Cards.stories.js +353 -0
  119. package/stories/primitives/FormGroups.stories.js +569 -0
  120. package/stories/primitives/Forms.stories.js +131 -0
  121. package/stories/primitives/Media.stories.js +203 -0
  122. package/stories/primitives/Tables.stories.js +232 -0
  123. package/stories/reference/ReferenceCatalog.stories.js +28 -0
  124. package/stories/reference/reference-catalog.js +413 -0
  125. package/stories/reference/reference-docs.js +302 -0
  126. package/stories/reference/reference-helpers.js +310 -0
  127. package/stories/utilities/GridSystem.stories.js +208 -0
  128. package/stories/utils/PdsAsk.stories.js +420 -0
  129. package/stories/utils/toast-utils.js +148 -0
@@ -0,0 +1,283 @@
1
+ import { html } from 'lit';
2
+
3
+ const toRgb = (raw) => {
4
+ if (!raw) {
5
+ return null;
6
+ }
7
+
8
+ const value = raw.trim();
9
+
10
+ if (!value) {
11
+ return null;
12
+ }
13
+
14
+ const hexMatch = value.match(/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i);
15
+ if (hexMatch) {
16
+ let hex = hexMatch[1];
17
+
18
+ if (hex.length === 3) {
19
+ hex = hex
20
+ .split('')
21
+ .map((ch) => ch + ch)
22
+ .join('');
23
+ }
24
+
25
+ if (hex.length === 8) {
26
+ hex = hex.slice(0, 6);
27
+ }
28
+
29
+ const intVal = parseInt(hex, 16);
30
+ return {
31
+ r: (intVal >> 16) & 255,
32
+ g: (intVal >> 8) & 255,
33
+ b: intVal & 255
34
+ };
35
+ }
36
+
37
+ const rgbMatch = value.match(/rgba?\(([^)]+)\)/i);
38
+ if (rgbMatch) {
39
+ const parts = rgbMatch[1]
40
+ .split(',')
41
+ .map((part) => part.trim())
42
+ .map((part) => (part.endsWith('%') ? (255 * parseFloat(part)) / 100 : parseFloat(part)));
43
+
44
+ if (parts.length < 3 || parts.some((part) => Number.isNaN(part))) {
45
+ return null;
46
+ }
47
+
48
+ return {
49
+ r: Math.max(0, Math.min(255, parts[0])),
50
+ g: Math.max(0, Math.min(255, parts[1])),
51
+ b: Math.max(0, Math.min(255, parts[2]))
52
+ };
53
+ }
54
+
55
+ return null;
56
+ };
57
+
58
+ const toRelativeLuminance = ({ r, g, b }) => {
59
+ const channel = (value) => {
60
+ const normalized = value / 255;
61
+ return normalized <= 0.04045
62
+ ? normalized / 12.92
63
+ : Math.pow((normalized + 0.055) / 1.055, 2.4);
64
+ };
65
+
66
+ const rLin = channel(r);
67
+ const gLin = channel(g);
68
+ const bLin = channel(b);
69
+
70
+ return 0.2126 * rLin + 0.7152 * gLin + 0.0722 * bLin;
71
+ };
72
+
73
+ const contrastRatio = (a, b) => {
74
+ const l1 = toRelativeLuminance(a);
75
+ const l2 = toRelativeLuminance(b);
76
+
77
+ const lighter = Math.max(l1, l2);
78
+ const darker = Math.min(l1, l2);
79
+
80
+ return (lighter + 0.05) / (darker + 0.05);
81
+ };
82
+
83
+ // Prefers the highest-contrast candidate for each swatch at runtime.
84
+ const chooseReadableTextColor = (colorName, shade, fallback) => {
85
+ if (typeof window === 'undefined' || !window.getComputedStyle) {
86
+ return fallback;
87
+ }
88
+
89
+ const style = window.getComputedStyle(document.documentElement);
90
+ const backgroundValue = style.getPropertyValue(`--color-${colorName}-${shade}`);
91
+ const background = toRgb(backgroundValue);
92
+
93
+ if (!background) {
94
+ return fallback;
95
+ }
96
+
97
+ const candidateSources = [
98
+ '--surface-inverse-text',
99
+ '--surface-text',
100
+ `--color-${colorName}-900`,
101
+ `--color-${colorName}-50`,
102
+ '#ffffff',
103
+ '#000000'
104
+ ];
105
+
106
+ let best = { value: fallback, ratio: 0 };
107
+
108
+ for (const source of candidateSources) {
109
+ let raw = source;
110
+
111
+ if (source.startsWith('--')) {
112
+ raw = style.getPropertyValue(source);
113
+ }
114
+
115
+ const rgb = toRgb(raw);
116
+
117
+ if (!rgb) {
118
+ continue;
119
+ }
120
+
121
+ const ratio = contrastRatio(background, rgb);
122
+
123
+ if (ratio > best.ratio) {
124
+ best = { value: `rgb(${Math.round(rgb.r)}, ${Math.round(rgb.g)}, ${Math.round(rgb.b)})`, ratio };
125
+ }
126
+ }
127
+
128
+ return best.value || fallback;
129
+ };
130
+
131
+ export default {
132
+ title: 'Foundations/Colors',
133
+ parameters: {
134
+ pds: {
135
+ tags: ['colors']
136
+ },
137
+ docs: {
138
+ description: {
139
+ component: 'Design tokens - colors, typography, spacing, icons'
140
+ }
141
+ }
142
+ },
143
+ argTypes: {
144
+ preset: {
145
+ control: 'select',
146
+ options: ['default', 'ocean-breeze', 'midnight-steel', 'sunset-vibes', 'forest-calm', 'lavender-dream'],
147
+ description: 'Choose a design preset'
148
+ },
149
+ primaryColor: {
150
+ control: 'color',
151
+ description: 'Override primary color'
152
+ },
153
+ secondaryColor: {
154
+ control: 'color',
155
+ description: 'Override secondary color'
156
+ }
157
+ }
158
+ };
159
+
160
+ const colorNames = [
161
+ 'primary',
162
+ 'secondary',
163
+ 'accent',
164
+ 'success',
165
+ 'warning',
166
+ 'danger',
167
+ 'info'
168
+ ];
169
+
170
+ const colorShades = [50, 100, 200, 300, 400, 500, 600, 700, 800];
171
+
172
+ const getFallbackTextColor = (color, shade) =>
173
+ shade >= 400
174
+ ? 'var(--surface-inverse-text, #ffffff)'
175
+ : `var(--color-${color}-900)`;
176
+
177
+ const colorScaleStoryStyles = html`
178
+ <style>
179
+ .color-scale-story-container {
180
+ padding: var(--spacing-8);
181
+ }
182
+ .color-scale-container {
183
+ margin-bottom: var(--spacing-8);
184
+ }
185
+ .color-scale-row {
186
+ display: flex;
187
+ align-items: center;
188
+ gap: var(--spacing-4);
189
+ }
190
+ .color-scale-label {
191
+ width: 7.5rem;
192
+ font-weight: 600;
193
+ }
194
+ .color-scale-swatches {
195
+ display: flex;
196
+ flex: 1;
197
+ }
198
+ .color-scale-swatch {
199
+ flex: 1;
200
+ min-height: 3.75rem;
201
+ padding: var(--spacing-4);
202
+ text-align: center;
203
+ transition: transform 0.2s, box-shadow 0.2s;
204
+ cursor: pointer;
205
+ position: relative;
206
+ z-index: 1;
207
+ }
208
+ .color-scale-swatch--hover {
209
+ transform: translateY(-0.25rem);
210
+ z-index: 10;
211
+ box-shadow: var(--shadow-md);
212
+ }
213
+ ${colorNames
214
+ .map((color) =>
215
+ colorShades
216
+ .map((shade) => {
217
+ const textColor = getFallbackTextColor(color, shade);
218
+ return `
219
+ .color-scale-swatch[data-color="${color}"][data-shade="${shade}"] {
220
+ background: var(--color-${color}-${shade});
221
+ color: ${textColor};
222
+ }
223
+ `;
224
+ })
225
+ .join('\n')
226
+ )
227
+ .join('\n')}
228
+ </style>
229
+ `;
230
+
231
+ const handleSwatchHoverEnter = (event) => {
232
+ event.currentTarget.classList.add('color-scale-swatch--hover');
233
+ };
234
+
235
+ const handleSwatchHoverLeave = (event) => {
236
+ event.currentTarget.classList.remove('color-scale-swatch--hover');
237
+ };
238
+
239
+ const renderColorScale = (colorName) => html`
240
+ <div class="color-scale-container">
241
+ <div class="color-scale-row">
242
+ <div class="color-scale-label">${colorName}</div>
243
+ <div class="color-scale-swatches">
244
+ ${colorShades.map(
245
+ (shade) => html`
246
+ <div
247
+ class="color-scale-swatch"
248
+ data-color=${colorName}
249
+ data-shade=${shade}
250
+ style=${`color: ${chooseReadableTextColor(colorName, shade, getFallbackTextColor(colorName, shade))}`}
251
+ @mouseover=${handleSwatchHoverEnter}
252
+ @mouseout=${handleSwatchHoverLeave}
253
+ title="${colorName}-${shade}"
254
+ >
255
+ ${shade}
256
+ </div>
257
+ `
258
+ )}
259
+ </div>
260
+ </div>
261
+ </div>
262
+ `;
263
+
264
+ export const Default = {
265
+ render: (args) => {
266
+ return html`
267
+ ${colorScaleStoryStyles}
268
+ <div class="story-container color-scale-story-container">
269
+ <h2>Color Scales</h2>
270
+ ${renderColorScale('primary')}
271
+ ${renderColorScale('secondary')}
272
+ ${renderColorScale('accent')}
273
+ ${renderColorScale('success')}
274
+ ${renderColorScale('warning')}
275
+ ${renderColorScale('danger')}
276
+ ${renderColorScale('info')}
277
+ </div>
278
+ `;
279
+ },
280
+ args: {
281
+ preset: 'default'
282
+ }
283
+ };
@@ -0,0 +1,305 @@
1
+ import { html } from 'lit';
2
+ import { presets } from '../../../../src/js/pds-core/pds-config.js';
3
+
4
+ const iconStoryStyles = html`
5
+ <style>
6
+ .icon-story-section {
7
+ padding: var(--spacing-4);
8
+ display: grid;
9
+ gap: var(--spacing-4);
10
+ }
11
+
12
+ .icon-story-description {
13
+ margin-bottom: var(--spacing-4);
14
+ opacity: 0.8;
15
+ max-width: 60ch;
16
+ }
17
+
18
+ .icon-story-grid {
19
+ display: flex;
20
+ gap: var(--spacing-3);
21
+ flex-wrap: wrap;
22
+ align-items: center;
23
+ }
24
+
25
+ .icon-story-size-grid {
26
+ display: grid;
27
+ gap: var(--spacing-4);
28
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
29
+ }
30
+
31
+ .icon-story-size-item {
32
+ display: grid;
33
+ gap: var(--spacing-2);
34
+ text-align: center;
35
+ justify-items: center;
36
+ }
37
+
38
+ .icon-story-filter {
39
+ display: grid;
40
+ justify-items: center;
41
+ gap: var(--spacing-2);
42
+ margin-bottom: var(--spacing-6);
43
+ }
44
+
45
+ .icon-story-filter__label {
46
+ font-weight: 600;
47
+ }
48
+
49
+ .icon-story-filter__input {
50
+ width: 100%;
51
+ max-width: 400px;
52
+ padding: var(--spacing-3);
53
+ border: 1px solid var(--color-border);
54
+ border-radius: var(--radius-md);
55
+ font-size: 1rem;
56
+ text-align: center;
57
+ background: var(--color-surface);
58
+ }
59
+
60
+ .icon-category {
61
+ display: grid;
62
+ gap: var(--spacing-4);
63
+ }
64
+
65
+ .icon-category__title {
66
+ text-transform: capitalize;
67
+ display: flex;
68
+ align-items: baseline;
69
+ gap: var(--spacing-2);
70
+ flex-wrap: wrap;
71
+ }
72
+
73
+ .icon-category__count {
74
+ font-size: 0.85rem;
75
+ font-weight: normal;
76
+ opacity: 0.6;
77
+ }
78
+
79
+ .icon-category__grid {
80
+ display: grid;
81
+ grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
82
+ gap: var(--spacing-3);
83
+ }
84
+
85
+ .icon-item {
86
+ display: flex;
87
+ flex-direction: column;
88
+ align-items: center;
89
+ gap: var(--spacing-2);
90
+ padding: var(--spacing-3);
91
+ border-radius: var(--radius-sm);
92
+ cursor: pointer;
93
+ transition: background-color 0.2s ease, color 0.2s ease;
94
+ }
95
+
96
+ .icon-item:hover {
97
+ background: var(--surface-elevated);
98
+ }
99
+
100
+ .icon-item--copied {
101
+ animation: iconItemCopied 0.4s ease;
102
+ background: var(--color-primary);
103
+ color: var(--color-surface);
104
+ }
105
+
106
+ .icon-item__label {
107
+ font-size: 0.75rem;
108
+ text-align: center;
109
+ word-break: break-word;
110
+ opacity: 0.8;
111
+ }
112
+
113
+ .icon-story-usage {
114
+ margin-top: var(--spacing-6);
115
+ display: grid;
116
+ gap: var(--spacing-3);
117
+ }
118
+
119
+ .icon-story-usage__code {
120
+ margin: 0;
121
+ padding: var(--spacing-3);
122
+ background: var(--surface-bg);
123
+ border-radius: var(--radius-sm);
124
+ overflow-x: auto;
125
+ }
126
+
127
+ @keyframes iconItemCopied {
128
+ 0% {
129
+ transform: scale(1);
130
+ }
131
+ 50% {
132
+ transform: scale(0.98);
133
+ }
134
+ 100% {
135
+ transform: scale(1);
136
+ }
137
+ }
138
+ </style>
139
+ `;
140
+
141
+ export default {
142
+ title: 'Foundations/Icons',
143
+ parameters: {
144
+ docs: {
145
+ description: {
146
+ component: 'Icon system using Phosphor icons with configurable sets per category'
147
+ }
148
+ }
149
+ }
150
+ };
151
+
152
+ export const CommonIcons = () => html`
153
+ ${iconStoryStyles}
154
+ <section class="icon-story-section">
155
+ <div>
156
+ <h3>Common Icons</h3>
157
+ <p class="icon-story-description">
158
+ Frequently used icons for everyday UI needs
159
+ </p>
160
+ </div>
161
+ <div class="icon-story-grid">
162
+ <pds-icon icon="heart" size="lg"></pds-icon>
163
+ <pds-icon icon="star" size="lg"></pds-icon>
164
+ <pds-icon icon="user" size="lg"></pds-icon>
165
+ <pds-icon icon="bell" size="lg"></pds-icon>
166
+ <pds-icon icon="magnifying-glass" size="lg"></pds-icon>
167
+ <pds-icon icon="list" size="lg"></pds-icon>
168
+ <pds-icon icon="x" size="lg"></pds-icon>
169
+ <pds-icon icon="check" size="lg"></pds-icon>
170
+ <pds-icon icon="gear" size="lg"></pds-icon>
171
+ <pds-icon icon="download" size="lg"></pds-icon>
172
+ </div>
173
+ </section>
174
+ `;
175
+
176
+ CommonIcons.storyName = 'Common Icons';
177
+
178
+ export const IconSizes = () => html`
179
+ ${iconStoryStyles}
180
+ <section class="icon-story-section">
181
+ <div>
182
+ <h3>Icon Sizes</h3>
183
+ <p class="icon-story-description">
184
+ Built-in sizing scale keeps visual hierarchy consistent across the UI.
185
+ </p>
186
+ </div>
187
+ <div class="icon-story-size-grid">
188
+ <div class="icon-story-size-item">
189
+ <pds-icon icon="heart" size="xs"></pds-icon>
190
+ <small class="text-muted">xs (16px)</small>
191
+ </div>
192
+ <div class="icon-story-size-item">
193
+ <pds-icon icon="heart" size="sm"></pds-icon>
194
+ <small class="text-muted">sm (20px)</small>
195
+ </div>
196
+ <div class="icon-story-size-item">
197
+ <pds-icon icon="heart" size="md"></pds-icon>
198
+ <small class="text-muted">md (24px)</small>
199
+ </div>
200
+ <div class="icon-story-size-item">
201
+ <pds-icon icon="heart" size="lg"></pds-icon>
202
+ <small class="text-muted">lg (32px)</small>
203
+ </div>
204
+ <div class="icon-story-size-item">
205
+ <pds-icon icon="heart" size="xl"></pds-icon>
206
+ <small class="text-muted">xl (48px)</small>
207
+ </div>
208
+ <div class="icon-story-size-item">
209
+ <pds-icon icon="heart" size="2xl"></pds-icon>
210
+ <small class="text-muted">2xl (64px)</small>
211
+ </div>
212
+ </div>
213
+ </section>
214
+ `;
215
+
216
+ IconSizes.storyName = 'Icon Sizes';
217
+
218
+ export const AllIcons = () => {
219
+ const iconConfig = presets.default.icons.include;
220
+
221
+ return html`
222
+ ${iconStoryStyles}
223
+ <section class="icon-story-section">
224
+ <div>
225
+ <h2>All Available Icons</h2>
226
+ <p class="icon-story-description">
227
+ Complete icon set from Phosphor Icons, organized by category. Click any icon name to copy it to clipboard.
228
+ </p>
229
+ </div>
230
+
231
+ <div class="icon-story-filter">
232
+ <span class="icon-story-filter__label" data-label>Filter icons</span>
233
+ <input
234
+ class="icon-story-filter__input"
235
+ type="search"
236
+ placeholder="Type to filter..."
237
+ @input="${(event) => {
238
+ const searchTerm = event.target.value.toLowerCase();
239
+ const storyRoot = event.target.closest('.icon-story-section');
240
+ const categories = storyRoot?.querySelectorAll('.icon-category');
241
+
242
+ categories?.forEach((category) => {
243
+ const items = category.querySelectorAll('.icon-item');
244
+ let visibleCount = 0;
245
+
246
+ items.forEach((item) => {
247
+ const iconName = item.dataset.iconName ?? '';
248
+ if (iconName.includes(searchTerm)) {
249
+ item.style.display = 'flex';
250
+ visibleCount += 1;
251
+ } else {
252
+ item.style.display = 'none';
253
+ }
254
+ });
255
+
256
+ category.style.display = visibleCount > 0 ? 'grid' : 'none';
257
+ });
258
+ }}"
259
+ />
260
+ </div>
261
+
262
+ ${Object.entries(iconConfig).map(
263
+ ([category, icons]) => html`
264
+ <article class="card icon-category">
265
+ <h3 class="icon-category__title">
266
+ ${category.replace(/([A-Z])/g, ' $1').trim()}
267
+ <span class="icon-category__count">(${icons.length} icons)</span>
268
+ </h3>
269
+
270
+ <div class="icon-category__grid">
271
+ ${icons.map(
272
+ (icon) => html`
273
+ <div
274
+ class="icon-item"
275
+ data-icon-name="${icon}"
276
+ @click="${(event) => {
277
+ navigator.clipboard.writeText(icon);
278
+ const target = event.currentTarget;
279
+ target.classList.add('icon-item--copied');
280
+ setTimeout(() => {
281
+ target.classList.remove('icon-item--copied');
282
+ }, 200);
283
+ }}"
284
+ >
285
+ <pds-icon icon="${icon}" size="lg"></pds-icon>
286
+ <span class="icon-item__label">${icon}</span>
287
+ </div>
288
+ `
289
+ )}
290
+ </div>
291
+ </article>
292
+ `
293
+ )}
294
+
295
+ <article class="card surface-elevated icon-story-usage">
296
+ <h4>Usage</h4>
297
+ <pre class="icon-story-usage__code"><code>&lt;pds-icon icon="heart" size="lg"&gt;&lt;/pds-icon&gt;
298
+ &lt;pds-icon icon="star" size="md"&gt;&lt;/pds-icon&gt;
299
+ &lt;pds-icon icon="user" size="sm"&gt;&lt;/pds-icon&gt;</code></pre>
300
+ </article>
301
+ </section>
302
+ `;
303
+ };
304
+
305
+ AllIcons.storyName = 'All Icons';