@pure-ds/storybook 0.5.39 → 0.5.41
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.
- package/.storybook/addons/html-preview/Panel.jsx +70 -7
- package/.storybook/addons/html-preview/preview.js +78 -3
- package/.storybook/main.js +3 -3
- package/.storybook/preview-head.html +1 -1
- package/dist/pds-reference.json +25 -297
- package/package.json +2 -2
- package/public/assets/js/app.js +19 -14
- package/public/assets/js/lit.js +3 -3
- package/public/assets/pds/components/pds-fab.js +4 -6
- package/public/assets/pds/external/lit.js +131 -0
- package/src/js/lit.js +54 -0
- package/src/js/pds-configurator/pds-demo.js +8 -0
- package/stories/components/PdsFab.stories.js +164 -127
- package/stories/components/PdsForm.stories.js +1 -1
- package/stories/components/PdsOmnibox.stories.js +22 -32
- package/stories/components/PdsScrollrow.stories.js +1 -1
- package/stories/components/PdsTabstrip.stories.js +1 -1
- package/stories/enhancements/Clip.stories.js +1 -1
- package/stories/enhancements/Dropdowns.stories.js +1 -1
- package/stories/enhancements/Toggles.stories.js +1 -1
- package/stories/foundations/Dividers.stories.js +1 -1
- package/stories/foundations/MeshGradients.stories.js +1 -1
- package/stories/foundations/SmartSurfaces.stories.js +1 -1
- package/stories/foundations/Typography.stories.js +1 -1
- package/stories/getting-started.md +1 -1
- package/stories/layout/LayoutOverview.stories.js +1 -1
- package/stories/layout/LayoutSystem.stories.js +1 -1
- package/stories/patterns/InteractiveStates.stories.js +1 -1
- package/stories/patterns/Utilities.stories.js +1 -1
- package/stories/primitives/Cards.stories.js +1 -1
- package/stories/primitives/HtmlFormGroups.stories.js +1 -1
|
@@ -109,11 +109,12 @@ const CheckIcon = () => (
|
|
|
109
109
|
);
|
|
110
110
|
|
|
111
111
|
export const Panel = ({ active }) => {
|
|
112
|
-
const [source, setSource] = useState({ markup: '', forms: [], omniboxes: [] });
|
|
112
|
+
const [source, setSource] = useState({ markup: '', forms: [], omniboxes: [], fabs: [] });
|
|
113
113
|
const [copied, setCopied] = useState(false);
|
|
114
114
|
const [highlightedMarkup, setHighlightedMarkup] = useState('');
|
|
115
115
|
const [highlightedforms, setHighlightedforms] = useState([]);
|
|
116
116
|
const [highlightedOmniboxes, setHighlightedOmniboxes] = useState([]);
|
|
117
|
+
const [highlightedFabs, setHighlightedFabs] = useState([]);
|
|
117
118
|
const shikiRef = useRef(null);
|
|
118
119
|
|
|
119
120
|
// Get Storybook theme to detect light/dark mode
|
|
@@ -232,10 +233,44 @@ export const Panel = ({ active }) => {
|
|
|
232
233
|
processOmniboxes();
|
|
233
234
|
}, [source.omniboxes, shikiTheme]);
|
|
234
235
|
|
|
236
|
+
// Highlight fab satellites when source or theme changes
|
|
237
|
+
useEffect(() => {
|
|
238
|
+
if (!source.fabs || source.fabs.length === 0) {
|
|
239
|
+
setHighlightedFabs([]);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const highlightCode = async (code) => {
|
|
244
|
+
if (!code) return '';
|
|
245
|
+
const highlighter = shikiRef.current || await loadShiki();
|
|
246
|
+
if (highlighter) {
|
|
247
|
+
try {
|
|
248
|
+
return highlighter.codeToHtml(code, { lang: 'javascript', theme: shikiTheme });
|
|
249
|
+
} catch (err) {
|
|
250
|
+
return `<pre><code>${escapeHtml(code)}</code></pre>`;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return `<pre><code>${escapeHtml(code)}</code></pre>`;
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const processFabs = async () => {
|
|
257
|
+
const highlighted = await Promise.all(
|
|
258
|
+
source.fabs.map(async (fab, index) => ({
|
|
259
|
+
id: fab.id ?? index,
|
|
260
|
+
label: fab.label,
|
|
261
|
+
satellites: await highlightCode(fab.satellites)
|
|
262
|
+
}))
|
|
263
|
+
);
|
|
264
|
+
setHighlightedFabs(highlighted);
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
processFabs();
|
|
268
|
+
}, [source.fabs, shikiTheme]);
|
|
269
|
+
|
|
235
270
|
useChannel({
|
|
236
271
|
[EVENTS.UPDATE_HTML]: (payload) => {
|
|
237
272
|
if (typeof payload === 'string') {
|
|
238
|
-
setSource({ markup: payload || '', forms: [], omniboxes: [] });
|
|
273
|
+
setSource({ markup: payload || '', forms: [], omniboxes: [], fabs: [] });
|
|
239
274
|
return;
|
|
240
275
|
}
|
|
241
276
|
|
|
@@ -243,18 +278,19 @@ export const Panel = ({ active }) => {
|
|
|
243
278
|
setSource({
|
|
244
279
|
markup: payload.markup || '',
|
|
245
280
|
forms: Array.isArray(payload.forms) ? payload.forms : [],
|
|
246
|
-
omniboxes: Array.isArray(payload.omniboxes) ? payload.omniboxes : []
|
|
281
|
+
omniboxes: Array.isArray(payload.omniboxes) ? payload.omniboxes : [],
|
|
282
|
+
fabs: Array.isArray(payload.fabs) ? payload.fabs : []
|
|
247
283
|
});
|
|
248
284
|
return;
|
|
249
285
|
}
|
|
250
286
|
|
|
251
|
-
setSource({ markup: '', forms: [], omniboxes: [] });
|
|
287
|
+
setSource({ markup: '', forms: [], omniboxes: [], fabs: [] });
|
|
252
288
|
}
|
|
253
289
|
});
|
|
254
290
|
|
|
255
291
|
// Request HTML update when panel becomes active
|
|
256
292
|
React.useEffect(() => {
|
|
257
|
-
if (active && !source.markup && source.forms.length === 0 && source.omniboxes.length === 0) {
|
|
293
|
+
if (active && !source.markup && source.forms.length === 0 && source.omniboxes.length === 0 && source.fabs.length === 0) {
|
|
258
294
|
// Trigger a re-extraction by emitting a request event
|
|
259
295
|
// The decorator will pick this up on the next render cycle
|
|
260
296
|
const container = document.querySelector('#storybook-root');
|
|
@@ -266,7 +302,7 @@ export const Panel = ({ active }) => {
|
|
|
266
302
|
}, 100);
|
|
267
303
|
}
|
|
268
304
|
}
|
|
269
|
-
}, [active, source.markup, source.forms.length, source.omniboxes.length]);
|
|
305
|
+
}, [active, source.markup, source.forms.length, source.omniboxes.length, source.fabs.length]);
|
|
270
306
|
|
|
271
307
|
const copyToClipboard = useCallback(async () => {
|
|
272
308
|
try {
|
|
@@ -282,8 +318,9 @@ export const Panel = ({ active }) => {
|
|
|
282
318
|
const hasMarkup = Boolean(source.markup);
|
|
283
319
|
const hasforms = source.forms.length > 0;
|
|
284
320
|
const hasOmniboxes = source.omniboxes.length > 0;
|
|
321
|
+
const hasFabs = source.fabs.length > 0;
|
|
285
322
|
|
|
286
|
-
if (!hasMarkup && !hasforms && !hasOmniboxes) {
|
|
323
|
+
if (!hasMarkup && !hasforms && !hasOmniboxes && !hasFabs) {
|
|
287
324
|
return (
|
|
288
325
|
<Container>
|
|
289
326
|
<EmptyState>
|
|
@@ -303,6 +340,31 @@ export const Panel = ({ active }) => {
|
|
|
303
340
|
</SectionWrapper>
|
|
304
341
|
)}
|
|
305
342
|
|
|
343
|
+
{hasFabs && (
|
|
344
|
+
<SectionWrapper>
|
|
345
|
+
<SectionHeading>satellites</SectionHeading>
|
|
346
|
+
{source.fabs.map((sourceFab, index) => {
|
|
347
|
+
const key = sourceFab.id ?? index;
|
|
348
|
+
const highlightedFab = highlightedFabs[index];
|
|
349
|
+
const label = source.fabs.length > 1 ? (sourceFab.label || `Fab ${index + 1}`) : null;
|
|
350
|
+
|
|
351
|
+
return (
|
|
352
|
+
<div key={key}>
|
|
353
|
+
{label && <Subheading>{label}</Subheading>}
|
|
354
|
+
{sourceFab.satellites && (
|
|
355
|
+
<CodeBlock
|
|
356
|
+
$compact
|
|
357
|
+
dangerouslySetInnerHTML={{
|
|
358
|
+
__html: highlightedFab?.satellites || `<pre><code>${escapeHtml(sourceFab.satellites)}</code></pre>`
|
|
359
|
+
}}
|
|
360
|
+
/>
|
|
361
|
+
)}
|
|
362
|
+
</div>
|
|
363
|
+
);
|
|
364
|
+
})}
|
|
365
|
+
</SectionWrapper>
|
|
366
|
+
)}
|
|
367
|
+
|
|
306
368
|
{hasforms && source.forms.map((sourceForm, index) => {
|
|
307
369
|
const key = sourceForm.id ?? index;
|
|
308
370
|
const highlightedForm = highlightedforms[index];
|
|
@@ -375,6 +437,7 @@ export const Panel = ({ active }) => {
|
|
|
375
437
|
);
|
|
376
438
|
})}
|
|
377
439
|
|
|
440
|
+
|
|
378
441
|
{hasMarkup && (
|
|
379
442
|
<CopyButton
|
|
380
443
|
onClick={copyToClipboard}
|
|
@@ -33,7 +33,8 @@ function formatHTML(html) {
|
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
const cleaned = formatted.trim();
|
|
37
|
+
return cleaned.replace(/\s([\w:-]+)=""/g, ' $1');
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
/**
|
|
@@ -45,10 +46,20 @@ function extractHTML(element) {
|
|
|
45
46
|
const clone = element.cloneNode(true);
|
|
46
47
|
|
|
47
48
|
// Clean up Storybook-specific attributes
|
|
49
|
+
const runtimeDataAttrs = new Set([
|
|
50
|
+
'data-original-icon',
|
|
51
|
+
'data-icon',
|
|
52
|
+
'data-uid',
|
|
53
|
+
'data-rendered',
|
|
54
|
+
'data-runtime',
|
|
55
|
+
'data-pds-runtime'
|
|
56
|
+
]);
|
|
57
|
+
|
|
48
58
|
const cleanElement = (el) => {
|
|
49
59
|
if (el.removeAttribute) {
|
|
50
60
|
el.removeAttribute('data-story-id');
|
|
51
61
|
el.removeAttribute('data-view-mode');
|
|
62
|
+
runtimeDataAttrs.forEach((attr) => el.removeAttribute(attr));
|
|
52
63
|
}
|
|
53
64
|
if (el.children) {
|
|
54
65
|
Array.from(el.children).forEach(cleanElement);
|
|
@@ -230,6 +241,39 @@ function generatePdsOmniboxMarkup(omniboxElement) {
|
|
|
230
241
|
return `<pds-omnibox${formattedAttrs}></pds-omnibox>`;
|
|
231
242
|
}
|
|
232
243
|
|
|
244
|
+
/**
|
|
245
|
+
* Generate realistic source code for pds-fab elements
|
|
246
|
+
*/
|
|
247
|
+
function generatePdsFabMarkup(fabElement) {
|
|
248
|
+
const attrs = [];
|
|
249
|
+
|
|
250
|
+
const stringAttrs = ['id', 'radius', 'spread', 'start-angle'];
|
|
251
|
+
stringAttrs.forEach((attr) => {
|
|
252
|
+
const value = fabElement.getAttribute(attr);
|
|
253
|
+
if (value !== null && value !== undefined && value !== '') {
|
|
254
|
+
attrs.push(`${attr}="${value}"`);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
if (Array.isArray(fabElement.satellites) && fabElement.satellites.length > 0) {
|
|
259
|
+
const satellitesSource =
|
|
260
|
+
fabElement.getAttribute?.('data-satellites-source') ||
|
|
261
|
+
fabElement.dataset?.satellitesSource ||
|
|
262
|
+
null;
|
|
263
|
+
attrs.push(satellitesSource || '.satellites=${satellites}');
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const formattedAttrs = attrs.length > 0
|
|
267
|
+
? '\n ' + attrs.join('\n ') + '\n'
|
|
268
|
+
: '';
|
|
269
|
+
|
|
270
|
+
const icon = fabElement.querySelector?.('pds-icon');
|
|
271
|
+
const iconMarkup = icon?.outerHTML || '<pds-icon icon="plus" size="lg"></pds-icon>';
|
|
272
|
+
const normalizedIcon = iconMarkup.replace(/\s([\w:-]+)=""/g, ' $1');
|
|
273
|
+
|
|
274
|
+
return `<pds-fab${formattedAttrs}>\n ${normalizedIcon}\n</pds-fab>`;
|
|
275
|
+
}
|
|
276
|
+
|
|
233
277
|
/**
|
|
234
278
|
* Global decorator that extracts and sends HTML to the panel
|
|
235
279
|
*/
|
|
@@ -247,7 +291,11 @@ export const withHTMLExtractor = (storyFn, context) => {
|
|
|
247
291
|
// Check if this story has pds-form or pds-omnibox elements
|
|
248
292
|
const pdsFormElements = Array.from(container.querySelectorAll('pds-form'));
|
|
249
293
|
const pdsOmniboxElements = Array.from(container.querySelectorAll('pds-omnibox'));
|
|
250
|
-
const
|
|
294
|
+
const pdsFabElements = Array.from(container.querySelectorAll('pds-fab'));
|
|
295
|
+
const hasSpecialElements =
|
|
296
|
+
pdsFormElements.length > 0 ||
|
|
297
|
+
pdsOmniboxElements.length > 0 ||
|
|
298
|
+
pdsFabElements.length > 0;
|
|
251
299
|
|
|
252
300
|
if (hasSpecialElements) {
|
|
253
301
|
// Generate realistic markup for pds-form / pds-omnibox stories
|
|
@@ -273,6 +321,11 @@ export const withHTMLExtractor = (storyFn, context) => {
|
|
|
273
321
|
markup += generatePdsOmniboxMarkup(omnibox);
|
|
274
322
|
});
|
|
275
323
|
|
|
324
|
+
// Add pds-fab markup
|
|
325
|
+
pdsFabElements.forEach(fab => {
|
|
326
|
+
markup += generatePdsFabMarkup(fab);
|
|
327
|
+
});
|
|
328
|
+
|
|
276
329
|
html = markup;
|
|
277
330
|
} else {
|
|
278
331
|
// No pds-form elements, use standard extraction
|
|
@@ -326,10 +379,32 @@ export const withHTMLExtractor = (storyFn, context) => {
|
|
|
326
379
|
})
|
|
327
380
|
.filter((entry) => entry.settings);
|
|
328
381
|
|
|
382
|
+
const fabs = pdsFabElements
|
|
383
|
+
.map((fab, index) => {
|
|
384
|
+
const label =
|
|
385
|
+
fab.getAttribute?.('id') ||
|
|
386
|
+
(pdsFabElements.length > 1 ? `Fab ${index + 1}` : 'Fab');
|
|
387
|
+
|
|
388
|
+
const satellitesSource =
|
|
389
|
+
fab.getAttribute?.('data-satellites-source') ||
|
|
390
|
+
fab.dataset?.satellitesSource ||
|
|
391
|
+
null;
|
|
392
|
+
|
|
393
|
+
const satellites = satellitesSource || serializeForDisplay(fab.satellites);
|
|
394
|
+
|
|
395
|
+
return {
|
|
396
|
+
id: index,
|
|
397
|
+
label,
|
|
398
|
+
satellites
|
|
399
|
+
};
|
|
400
|
+
})
|
|
401
|
+
.filter((entry) => entry.satellites);
|
|
402
|
+
|
|
329
403
|
channel.emit(EVENTS.UPDATE_HTML, {
|
|
330
404
|
markup: html || '',
|
|
331
405
|
forms,
|
|
332
|
-
omniboxes
|
|
406
|
+
omniboxes,
|
|
407
|
+
fabs
|
|
333
408
|
});
|
|
334
409
|
}
|
|
335
410
|
};
|
package/.storybook/main.js
CHANGED
|
@@ -68,10 +68,10 @@ const config = {
|
|
|
68
68
|
process.cwd()
|
|
69
69
|
];
|
|
70
70
|
|
|
71
|
-
// Ensure Lit import alias is resolved
|
|
71
|
+
// Ensure Lit import alias is resolved to PDS bundle
|
|
72
72
|
const aliases = {
|
|
73
73
|
...config.resolve.alias,
|
|
74
|
-
'#pds/lit': 'lit',
|
|
74
|
+
'#pds/lit': resolve(pdsSrcPath, 'js/lit.js'),
|
|
75
75
|
};
|
|
76
76
|
|
|
77
77
|
// In monorepo, pds-configurator is in a separate package, not in src/js
|
|
@@ -184,7 +184,7 @@ const config = {
|
|
|
184
184
|
config.resolve.alias['@user/pds-config'] = resolve(currentDirname, '../default-pds.config.js');
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
// Support absolute path imports like: import { html } from '/assets/
|
|
187
|
+
// Support absolute path imports like: import { html } from '/assets/pds/external/lit.js';
|
|
188
188
|
// Vite blocks direct imports from public/, so we disable Vite's public directory
|
|
189
189
|
// handling (Storybook uses staticDirs instead) and resolve these imports ourselves.
|
|
190
190
|
const userPublicPath = resolve(process.cwd(), 'public');
|