@pure-ds/storybook 0.7.31 → 0.7.46

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 (70) hide show
  1. package/.storybook/docs.css +6 -3
  2. package/.storybook/htmlPreview.css +14 -8
  3. package/.storybook/main.js +14 -4
  4. package/.storybook/preview.js +327 -92
  5. package/.storybook/shiki.js +3 -1
  6. package/dist/pds-reference.json +168 -69
  7. package/package.json +2 -2
  8. package/public/assets/js/app.js +5 -5
  9. package/public/assets/js/pds-autocomplete.js +4 -4
  10. package/public/assets/js/pds-enhancers.js +1 -1
  11. package/public/assets/js/pds-localization.js +1 -1
  12. package/public/assets/js/pds-manager.js +68 -71
  13. package/public/assets/js/pds.js +2 -2
  14. package/public/assets/locales/nl-NL.json +442 -0
  15. package/public/assets/pds/components/pds-calendar.js +4 -4
  16. package/public/assets/pds/components/pds-daterange.js +11 -8
  17. package/public/assets/pds/components/pds-drawer.js +18 -2
  18. package/public/assets/pds/components/pds-form.js +22 -22
  19. package/public/assets/pds/components/pds-icon.js +9 -1
  20. package/public/assets/pds/components/pds-live-edit.js +54 -486
  21. package/public/assets/pds/components/pds-live-importer.js +66 -66
  22. package/public/assets/pds/components/pds-live-template-canvas.js +3 -3
  23. package/public/assets/pds/components/pds-locale.js +1132 -0
  24. package/public/assets/pds/components/pds-omnibox.js +92 -12
  25. package/public/assets/pds/components/pds-rating.js +5 -3
  26. package/public/assets/pds/components/pds-tags.js +5 -5
  27. package/public/assets/pds/components/pds-theme.js +4 -4
  28. package/public/assets/pds/components/pds-toaster.js +6 -6
  29. package/public/assets/pds/components/pds-treeview.js +8 -4
  30. package/public/assets/pds/components/pds-upload.js +7 -6
  31. package/public/assets/pds/core/pds-autocomplete.js +4 -4
  32. package/public/assets/pds/core/pds-enhancers.js +1 -1
  33. package/public/assets/pds/core/pds-localization.js +1 -1
  34. package/public/assets/pds/core/pds-manager.js +68 -71
  35. package/public/assets/pds/core.js +2 -2
  36. package/public/assets/pds/external/shiki.js +1 -1
  37. package/public/assets/pds/vscode-custom-data.json +10 -0
  38. package/src/js/app.js +1 -1
  39. package/src/js/common/localization-resource-provider.js +88 -21
  40. package/src/js/common/localization.js +219 -5
  41. package/src/js/external/shiki.js +1 -1
  42. package/src/js/pds-autocomplete.js +69 -1
  43. package/src/js/pds-core/pds-config.js +20 -2
  44. package/src/js/pds-core/pds-enhancers-meta.js +13 -8
  45. package/src/js/pds-core/pds-enhancers.js +102 -125
  46. package/src/js/pds-core/pds-generator.js +13 -13
  47. package/src/js/pds-core/pds-live.js +21 -8
  48. package/src/js/pds-core/pds-ontology.js +8 -2
  49. package/src/js/pds-core/pds-start-helpers.js +12 -7
  50. package/src/js/pds.d.ts +2 -0
  51. package/src/js/pds.js +86 -20
  52. package/stories/WhatIsPDS.md +1 -1
  53. package/stories/components/PdsDrawer.stories.js +554 -240
  54. package/stories/components/PdsForm.stories.js +9 -1
  55. package/stories/components/PdsLocale.stories.js +86 -0
  56. package/stories/components/PdsOmnibox.stories.js +206 -0
  57. package/stories/enhancements/Dropdowns.stories.js +19 -17
  58. package/stories/foundations/Colors.stories.js +3 -1
  59. package/stories/getting-started.md +0 -10
  60. package/stories/reference/pds-object-docs.js +588 -0
  61. package/stories/reference/reference-catalog.js +4 -7
  62. package/stories/reference/reference-docs.js +91 -13
  63. package/stories/reference/reference-helpers.js +4 -3
  64. package/stories/utils/PdsAsk.stories.js +183 -9
  65. package/stories/utils/PdsObjectApi.stories.js +43 -8
  66. package/stories/utils/PdsParse.stories.js +4 -8
  67. package/stories/utils/PdsToast.stories.js +4 -8
  68. package/stories/utils/navigation.js +2 -2
  69. package/stories/utils/pds-object-meta.js +42 -0
  70. package/stories/utils/shiki.js +107 -19
@@ -2,9 +2,12 @@
2
2
 
3
3
  /* Override Storybook's default mono font for code panels */
4
4
  pre, code, .docblock-source pre, .docblock-source code {
5
- font-family: 'Source Code Pro', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace !important;
6
- font-size: 13.6px;
7
- line-height: 24px;
5
+ font-family: var(--pds-shiki-font-family, 'Source Code Pro', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace) !important;
6
+ font-size: var(--pds-shiki-font-size, 13.6px);
7
+ line-height: var(--pds-shiki-line-height, 24px);
8
+ -webkit-font-smoothing: antialiased;
9
+ -moz-osx-font-smoothing: grayscale;
10
+ text-rendering: geometricPrecision;
8
11
  }
9
12
 
10
13
  /* Hide ALL story previews and interactive elements in Docs */
@@ -39,13 +39,16 @@
39
39
  padding: var(--spacing-4, 1rem);
40
40
  border-radius: var(--radius-md, 4px);
41
41
  overflow-x: auto;
42
- font-size: 13.6px;
43
- line-height: 24px;
44
- tab-size: 2;
42
+ font-size: var(--pds-shiki-font-size, 13.6px);
43
+ line-height: var(--pds-shiki-line-height, 24px);
44
+ tab-size: var(--pds-shiki-tab-size, 2);
45
45
  }
46
46
 
47
47
  .html-source-content pre code {
48
- font-family: 'Source Code Pro', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
48
+ font-family: var(--pds-shiki-font-family, 'Source Code Pro', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
49
+ -webkit-font-smoothing: antialiased;
50
+ -moz-osx-font-smoothing: grayscale;
51
+ text-rendering: geometricPrecision;
49
52
  }
50
53
 
51
54
  /* Fallback pre styling (before Shiki loads) */
@@ -54,10 +57,13 @@
54
57
  padding: var(--spacing-4, 1rem);
55
58
  border-radius: var(--radius-md, 4px);
56
59
  overflow-x: auto;
57
- font-family: 'Source Code Pro', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
58
- font-size: 13.6px;
59
- line-height: 24px;
60
- tab-size: 2;
60
+ font-family: var(--pds-shiki-font-family, 'Source Code Pro', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
61
+ font-size: var(--pds-shiki-font-size, 13.6px);
62
+ line-height: var(--pds-shiki-line-height, 24px);
63
+ tab-size: var(--pds-shiki-tab-size, 2);
64
+ -webkit-font-smoothing: antialiased;
65
+ -moz-osx-font-smoothing: grayscale;
66
+ text-rendering: geometricPrecision;
61
67
  background: var(--color-surface-raised, #282c34);
62
68
  color: var(--color-text-primary, #abb2bf);
63
69
  }
@@ -180,11 +180,21 @@ const config = {
180
180
  config.resolve.alias.push({ find: '../../../../src', replacement: pdsSrcPath });
181
181
 
182
182
  // Try to resolve user's pds.config.js
183
- const userConfigPath = resolve(process.cwd(), 'pds.config.js');
184
- if (fs.existsSync(userConfigPath)) {
185
- config.resolve.alias.push({ find: '@user/pds-config', replacement: userConfigPath });
183
+ const packageRoot = resolve(currentDirname, '..');
184
+ const monorepoRoot = resolve(currentDirname, '../../..');
185
+ const cwdUserConfigPath = resolve(process.cwd(), 'pds.config.js');
186
+ const monorepoUserConfigPath = resolve(monorepoRoot, 'pds.config.js');
187
+
188
+ const userConfigCandidates = process.cwd() === packageRoot
189
+ ? [monorepoUserConfigPath, cwdUserConfigPath]
190
+ : [cwdUserConfigPath, monorepoUserConfigPath];
191
+
192
+ const resolvedUserConfigPath = userConfigCandidates.find((candidate) => fs.existsSync(candidate));
193
+
194
+ if (resolvedUserConfigPath) {
195
+ config.resolve.alias.push({ find: '@user/pds-config', replacement: resolvedUserConfigPath });
186
196
  } else {
187
- // Fallback to a default config file if user config doesn't exist
197
+ // Fallback to a default config file if user config doesn't exist
188
198
  config.resolve.alias.push({ find: '@user/pds-config', replacement: resolve(currentDirname, '../default-pds.config.js') });
189
199
  }
190
200
 
@@ -3,17 +3,22 @@ import { SELECT_STORY, UPDATE_GLOBALS } from '@storybook/core-events';
3
3
  import React from 'react';
4
4
  import { html } from 'lit';
5
5
  import { Title, Subtitle, Description as DocsDescription, Controls } from '@storybook/blocks';
6
- import { PDS } from '@pds-src/js/pds.js';
6
+ import { PDS } from '#pds';
7
7
  import { presets } from '@pds-src/js/pds-core/pds-config.js';
8
8
  import { Generator } from '@pds-src/js/pds-core/pds-generator.js';
9
9
  import { applyStyles } from '@pds-src/js/pds-core/pds-runtime.js';
10
+ import { stripFunctions } from '@pds-src/js/pds-core/pds-start-helpers.js';
10
11
  import { config as userConfig } from '@user/pds-config';
11
12
  import { withHTMLExtractor } from './addons/html-preview/preview.js';
12
13
  import { withDescription } from './addons/description/preview.js';
14
+ import { ensureSharedShikiStyles, preloadShiki } from './shiki.js';
13
15
  import './htmlPreview.css';
14
16
  import './docs.css';
15
17
  import { toastFormData } from '../stories/utils/toast-utils.js';
16
18
 
19
+ ensureSharedShikiStyles();
20
+ preloadShiki();
21
+
17
22
  // Expose toastFormData globally for inline event handlers
18
23
  window.toastFormData = toastFormData;
19
24
 
@@ -75,8 +80,127 @@ const getInitialPreset = () => {
75
80
  return 'default'; // Default preset
76
81
  };
77
82
 
83
+ const STORYBOOK_LOCALE_STORAGE_KEY = 'storybook-pds-locale';
84
+
85
+ const normalizeLocale = (value) => String(value || '').trim().toLowerCase();
86
+
87
+ const getConfiguredLocales = () => {
88
+ const configuredLocales = userConfig?.localization?.locales;
89
+ const providerLocales = userConfig?.localization?.provider?.locales;
90
+ const sourceLocales = Array.isArray(configuredLocales) && configuredLocales.length
91
+ ? configuredLocales
92
+ : Array.isArray(providerLocales) && providerLocales.length
93
+ ? providerLocales
94
+ : ['en'];
95
+
96
+ const seen = new Set();
97
+ return sourceLocales.reduce((result, locale) => {
98
+ const normalized = normalizeLocale(locale);
99
+ if (!normalized || seen.has(normalized)) return result;
100
+ seen.add(normalized);
101
+ result.push(normalized);
102
+ return result;
103
+ }, []);
104
+ };
105
+
106
+ const resolveSupportedLocale = (value, supportedLocales = [], fallbackLocale = 'en') => {
107
+ const normalizedValue = normalizeLocale(value);
108
+ const normalizedFallback = normalizeLocale(fallbackLocale) || 'en';
109
+ const normalizedSupported = Array.isArray(supportedLocales)
110
+ ? supportedLocales.map((locale) => normalizeLocale(locale)).filter(Boolean)
111
+ : [];
112
+
113
+ if (!normalizedSupported.length) return normalizedFallback;
114
+
115
+ const exactMatch = normalizedSupported.find((locale) => locale === normalizedValue);
116
+ if (exactMatch) return exactMatch;
117
+
118
+ const requestedBase = normalizedValue.split('-')[0];
119
+ const baseMatch = normalizedSupported.find((locale) => locale.split('-')[0] === requestedBase);
120
+ if (baseMatch) return baseMatch;
121
+
122
+ const fallbackMatch = normalizedSupported.find((locale) => locale === normalizedFallback);
123
+ if (fallbackMatch) return fallbackMatch;
124
+
125
+ return normalizedSupported[0];
126
+ };
127
+
128
+ const getInitialLocale = (supportedLocales, fallbackLocale) => {
129
+ try {
130
+ const sessionLocale = sessionStorage.getItem(STORYBOOK_LOCALE_STORAGE_KEY);
131
+ if (sessionLocale) {
132
+ return resolveSupportedLocale(sessionLocale, supportedLocales, fallbackLocale);
133
+ }
134
+
135
+ const storedLocale = localStorage.getItem(STORYBOOK_LOCALE_STORAGE_KEY);
136
+ if (storedLocale) {
137
+ return resolveSupportedLocale(storedLocale, supportedLocales, fallbackLocale);
138
+ }
139
+
140
+ const urlParams = new URLSearchParams(window.location.search);
141
+ const urlLocale = urlParams.get('locale');
142
+ if (urlLocale) {
143
+ return resolveSupportedLocale(urlLocale, supportedLocales, fallbackLocale);
144
+ }
145
+ } catch (error) {
146
+ console.warn('Failed to read locale from storage:', error);
147
+ }
148
+
149
+ return resolveSupportedLocale(fallbackLocale, supportedLocales, fallbackLocale);
150
+ };
151
+
152
+ const formatLocaleTitle = (locale) => {
153
+ const normalized = normalizeLocale(locale);
154
+ if (!normalized) return locale;
155
+
156
+ const [languageCode, regionCode] = normalized.split('-');
157
+ let languageLabel = languageCode.toUpperCase();
158
+
159
+ try {
160
+ if (typeof Intl !== 'undefined' && typeof Intl.DisplayNames === 'function') {
161
+ const displayNames = new Intl.DisplayNames(['en'], { type: 'language' });
162
+ languageLabel = displayNames.of(languageCode) || languageLabel;
163
+ }
164
+ } catch {}
165
+
166
+ if (regionCode) {
167
+ return `${languageLabel} (${languageCode}-${regionCode.toUpperCase()})`;
168
+ }
169
+
170
+ return `${languageLabel} (${languageCode})`;
171
+ };
172
+
173
+ const storybookLocales = getConfiguredLocales();
174
+ if (!storybookLocales.length) {
175
+ storybookLocales.push('en');
176
+ }
177
+
178
+ const initialDocumentLocale = typeof document !== 'undefined'
179
+ ? document.documentElement?.getAttribute('lang')
180
+ : null;
181
+
182
+ const defaultStorybookLocale = resolveSupportedLocale(
183
+ userConfig?.localization?.locale || initialDocumentLocale || 'en',
184
+ storybookLocales,
185
+ storybookLocales[0] || 'en'
186
+ );
187
+
78
188
  const initialPreset = getInitialPreset();
189
+ const initialLocale = getInitialLocale(storybookLocales, defaultStorybookLocale);
79
190
  console.log('🎨 Starting PDS initialization with preset:', initialPreset);
191
+ console.log('🌍 Starting locale for Storybook:', initialLocale);
192
+
193
+ const clonePresetDesign = (presetConfig) => {
194
+ const cloneCandidate = stripFunctions(presetConfig);
195
+ if (typeof structuredClone === 'function') {
196
+ return structuredClone(cloneCandidate);
197
+ }
198
+ return JSON.parse(JSON.stringify(cloneCandidate));
199
+ };
200
+
201
+ if (typeof document !== 'undefined' && document.documentElement) {
202
+ document.documentElement.setAttribute('lang', initialLocale);
203
+ }
80
204
 
81
205
  // Helper to detect docs pages - used to prevent PDS from interfering
82
206
  function isDocsPage() {
@@ -89,14 +213,22 @@ function isDocsPage() {
89
213
  }
90
214
  }
91
215
 
92
- function inferCodeLanguage(codeEl) {
93
- if (!codeEl) return 'html';
94
- const className = codeEl.className || '';
216
+ function inferCodeLanguage(codeEl, preEl) {
217
+ if (!codeEl && !preEl) return 'html';
218
+
219
+ const className = codeEl?.className || '';
95
220
  const languageMatch = className.match(/(?:language|lang)-([a-z0-9-]+)/i);
96
221
  if (languageMatch?.[1]) {
97
222
  return languageMatch[1].toLowerCase();
98
223
  }
99
- return codeEl.getAttribute('data-lang') || 'html';
224
+
225
+ const preClassName = preEl?.className || '';
226
+ const preLanguageMatch = preClassName.match(/(?:language|lang)-([a-z0-9-]+)/i);
227
+ if (preLanguageMatch?.[1]) {
228
+ return preLanguageMatch[1].toLowerCase();
229
+ }
230
+
231
+ return codeEl?.getAttribute('data-lang') || preEl?.getAttribute('data-lang') || 'html';
100
232
  }
101
233
 
102
234
  function upgradeLegacyCodeBlocks(root) {
@@ -108,10 +240,19 @@ function upgradeLegacyCodeBlocks(root) {
108
240
  const preEl = codeEl.parentElement;
109
241
  if (!preEl || preEl.closest('pds-code')) return;
110
242
 
243
+ // Keep Shiki-rendered blocks intact; they already carry correct language + theme.
244
+ if (
245
+ preEl.classList.contains('shiki') ||
246
+ preEl.classList.contains('pds-shiki-block') ||
247
+ preEl.hasAttribute('data-pds-shiki')
248
+ ) {
249
+ return;
250
+ }
251
+
111
252
  const content = codeEl.textContent || '';
112
253
  if (!content.trim()) return;
113
254
 
114
- const lang = inferCodeLanguage(codeEl);
255
+ const lang = inferCodeLanguage(codeEl, preEl);
115
256
  const pdsCode = document.createElement('pds-code');
116
257
  pdsCode.setAttribute('lang', lang);
117
258
  pdsCode.code = content;
@@ -119,6 +260,37 @@ function upgradeLegacyCodeBlocks(root) {
119
260
  });
120
261
  }
121
262
 
263
+ const observeCodeBlocks = (() => {
264
+ const observedRoots = new WeakSet();
265
+ return (root) => {
266
+ if (!root || observedRoots.has(root)) return;
267
+
268
+ const observer = new MutationObserver(() => {
269
+ upgradeLegacyCodeBlocks(root);
270
+ });
271
+
272
+ observer.observe(root, { childList: true, subtree: true });
273
+ observedRoots.add(root);
274
+ };
275
+ })();
276
+
277
+ function scheduleCodeBlockUpgrade(root) {
278
+ if (!root) return;
279
+
280
+ const runUpgrade = () => upgradeLegacyCodeBlocks(root);
281
+ runUpgrade();
282
+ requestAnimationFrame(runUpgrade);
283
+ setTimeout(runUpgrade, 60);
284
+ setTimeout(runUpgrade, 220);
285
+
286
+ void ensurePdsCodeLoaded().then(() => {
287
+ runUpgrade();
288
+ observeCodeBlocks(root);
289
+ });
290
+
291
+ observeCodeBlocks(root);
292
+ }
293
+
122
294
  let liveGenerator = null;
123
295
  const setLiveGenerator = (generator) => {
124
296
  if (generator && typeof generator === 'object') {
@@ -155,6 +327,7 @@ PDS.addEventListener('pds:ready', (event) => {
155
327
  // Merge user config
156
328
  if (userConfig) {
157
329
  if (userConfig.mode) pdsOptions.mode = userConfig.mode;
330
+ if (userConfig.localization) pdsOptions.localization = userConfig.localization;
158
331
  if (userConfig.autoDefine) {
159
332
  // Merge autoDefine options
160
333
  pdsOptions.autoDefine = {
@@ -177,6 +350,10 @@ PDS.addEventListener('pds:ready', (event) => {
177
350
 
178
351
  // Store PDS designer globally for reuse
179
352
  PDS.currentPreset = initialPreset;
353
+
354
+ if (typeof document !== 'undefined' && document.documentElement) {
355
+ document.documentElement.setAttribute('lang', initialLocale);
356
+ }
180
357
  })();
181
358
 
182
359
  // Style protection disabled - decorator controls when PDS styles are applied
@@ -188,6 +365,42 @@ PDS.addEventListener('pds:ready', (event) => {
188
365
  // Track current view mode globally for other code to check
189
366
  let currentViewMode = 'story';
190
367
  let toolbarTheme = null;
368
+ let toolbarLocale = initialLocale;
369
+
370
+ const setToolbarLocaleValue = (value) => {
371
+ const supportedLocale = resolveSupportedLocale(value, storybookLocales, defaultStorybookLocale);
372
+ if (!supportedLocale) return;
373
+ toolbarLocale = supportedLocale;
374
+ };
375
+
376
+ const persistStorybookLocale = (locale) => {
377
+ const supportedLocale = resolveSupportedLocale(locale, storybookLocales, defaultStorybookLocale);
378
+ if (!supportedLocale) return;
379
+
380
+ try {
381
+ sessionStorage.setItem(STORYBOOK_LOCALE_STORAGE_KEY, supportedLocale);
382
+ localStorage.setItem(STORYBOOK_LOCALE_STORAGE_KEY, supportedLocale);
383
+ } catch (error) {
384
+ console.warn('Failed to store locale:', error);
385
+ }
386
+ };
387
+
388
+ const applyStorybookLocale = (locale, { persist = true } = {}) => {
389
+ const supportedLocale = resolveSupportedLocale(locale, storybookLocales, defaultStorybookLocale);
390
+ if (!supportedLocale) return null;
391
+
392
+ if (persist) {
393
+ persistStorybookLocale(supportedLocale);
394
+ }
395
+
396
+ setToolbarLocaleValue(supportedLocale);
397
+
398
+ if (typeof document !== 'undefined' && document.documentElement) {
399
+ document.documentElement.setAttribute('lang', supportedLocale);
400
+ }
401
+
402
+ return supportedLocale;
403
+ };
191
404
 
192
405
  const setToolbarThemeValue = (value) => {
193
406
  if (!value) return;
@@ -253,7 +466,13 @@ const withPDS = (story, context) => {
253
466
  const nonPdsSheets = document.adoptedStyleSheets.filter(s => !s._pds);
254
467
  document.adoptedStyleSheets = nonPdsSheets;
255
468
  }
256
- return story();
469
+ const docsStory = story();
470
+ requestAnimationFrame(() => {
471
+ requestAnimationFrame(() => {
472
+ scheduleCodeBlockUpgrade(document.getElementById('docs-root'));
473
+ });
474
+ });
475
+ return docsStory;
257
476
  }
258
477
 
259
478
  console.log('🎬 withPDS decorator called for:', context.title);
@@ -353,7 +572,7 @@ const withPDS = (story, context) => {
353
572
 
354
573
  // Initial adoption - run multiple times to catch lazy components
355
574
  setTimeout(() => {
356
- upgradeLegacyCodeBlocks(document.querySelector('#storybook-root'));
575
+ scheduleCodeBlockUpgrade(document.querySelector('#storybook-root'));
357
576
  }, 0);
358
577
  setTimeout(adoptAllShadowStyles, 0);
359
578
  setTimeout(adoptAllShadowStyles, 100);
@@ -420,7 +639,7 @@ const withGlobalsHandler = (story, context) => {
420
639
  console.log(`🎨 Applying preset via decorator: ${presetConfig.name || globals.preset}`);
421
640
 
422
641
  const generatorOptions = {
423
- design: structuredClone(presetConfig),
642
+ design: clonePresetDesign(presetConfig),
424
643
  log: (...args) => console.log('🟦 [Generator]', ...args)
425
644
  };
426
645
 
@@ -447,6 +666,18 @@ const withGlobalsHandler = (story, context) => {
447
666
  if (globals?.theme) {
448
667
  setToolbarThemeValue(globals.theme);
449
668
  }
669
+
670
+ if (globals?.locale) {
671
+ const requestedLocale = resolveSupportedLocale(globals.locale, storybookLocales, defaultStorybookLocale);
672
+ const activeLocale = normalizeLocale(document.documentElement?.getAttribute('lang') || toolbarLocale);
673
+
674
+ if (requestedLocale && requestedLocale !== activeLocale) {
675
+ applyStorybookLocale(requestedLocale, { persist: true });
676
+ } else if (requestedLocale && document.documentElement?.getAttribute('lang') !== requestedLocale) {
677
+ document.documentElement.setAttribute('lang', requestedLocale);
678
+ setToolbarLocaleValue(requestedLocale);
679
+ }
680
+ }
450
681
 
451
682
  return story();
452
683
  };
@@ -1408,6 +1639,7 @@ const withRelatedStories = (story, context) => {
1408
1639
  requestAnimationFrame(() => {
1409
1640
  if (context.viewMode === 'docs') {
1410
1641
  pruneDocsStories();
1642
+ scheduleCodeBlockUpgrade(document.getElementById('docs-root'));
1411
1643
  renderRelatedFooter(context);
1412
1644
  removeRelatedOverlay();
1413
1645
  return;
@@ -1539,10 +1771,23 @@ const preview = {
1539
1771
  dynamicTitle: true
1540
1772
  }
1541
1773
  },
1774
+ locale: {
1775
+ name: 'Locale',
1776
+ description: 'PDS locale',
1777
+ defaultValue: initialLocale,
1778
+ toolbar: {
1779
+ icon: 'globe',
1780
+ items: storybookLocales.map((locale) => ({
1781
+ value: locale,
1782
+ title: formatLocaleTitle(locale)
1783
+ })),
1784
+ dynamicTitle: true
1785
+ }
1786
+ },
1542
1787
  preset: {
1543
1788
  name: 'Preset',
1544
1789
  description: 'Design preset',
1545
- defaultValue: initialPreset, // Use the preset loaded from storage
1790
+ defaultValue: initialPreset,
1546
1791
  toolbar: {
1547
1792
  icon: 'paintbrush',
1548
1793
  items: Object.keys(presets)
@@ -1551,25 +1796,20 @@ const preview = {
1551
1796
  const bPreset = presets[b];
1552
1797
  const aTags = aPreset.tags || [];
1553
1798
  const bTags = bPreset.tags || [];
1554
-
1555
- // Check if featured
1799
+
1556
1800
  const aFeatured = aTags.includes('featured');
1557
1801
  const bFeatured = bTags.includes('featured');
1558
-
1559
1802
  if (aFeatured && !bFeatured) return -1;
1560
1803
  if (!aFeatured && bFeatured) return 1;
1561
-
1562
- // Check if has any tags
1804
+
1563
1805
  const aHasTags = aTags.length > 0;
1564
1806
  const bHasTags = bTags.length > 0;
1565
-
1566
1807
  if (aHasTags && !bHasTags) return -1;
1567
1808
  if (!aHasTags && bHasTags) return 1;
1568
-
1569
- // Alphabetical by name
1809
+
1570
1810
  return (aPreset.name || a).localeCompare(bPreset.name || b);
1571
1811
  })
1572
- .map(key => ({
1812
+ .map((key) => ({
1573
1813
  value: key,
1574
1814
  title: presets[key].name || key
1575
1815
  })),
@@ -1579,102 +1819,97 @@ const preview = {
1579
1819
  }
1580
1820
  };
1581
1821
 
1582
- // Listen to theme and preset changes from toolbar
1583
1822
  if (typeof window !== 'undefined') {
1584
1823
  console.log('👂 Setting up message listener for toolbar changes...');
1585
-
1824
+
1586
1825
  window.addEventListener('message', async (event) => {
1587
- if(event.data?.type == null) return;
1826
+ if (event.data?.type == null) return;
1588
1827
 
1589
1828
  console.log('📨 Message received:', event.data?.type, event.data);
1590
-
1829
+
1591
1830
  if (event.data?.type === 'SET_GLOBALS') {
1592
1831
  console.log('✅ SET_GLOBALS detected, globals:', event.data.globals);
1593
1832
  const { globals } = event.data;
1594
-
1833
+
1595
1834
  if (globals?.theme) {
1596
1835
  console.log('🌙 Theme change requested:', globals.theme);
1597
-
1598
- // Set data-theme attribute on body for PDS theme system
1599
1836
  document.body.setAttribute('data-theme', globals.theme);
1600
-
1601
- // Also use PDS.theme property
1602
1837
  PDS.theme = globals.theme;
1603
-
1604
1838
  console.log('✅ Theme applied:', globals.theme);
1605
1839
  setToolbarThemeValue(globals.theme);
1606
1840
  }
1607
-
1841
+
1608
1842
  if (globals?.preset) {
1609
1843
  console.log('🔔 SET_GLOBALS message received with preset:', globals.preset);
1610
1844
  console.log('📦 Current stored preset:', PDS.currentPreset);
1611
-
1612
- // Skip if already on this preset
1845
+
1613
1846
  if (globals.preset === PDS.currentPreset) {
1614
1847
  console.log('⏭️ Preset unchanged, skipping');
1615
- return;
1616
- }
1617
-
1618
- try {
1619
- console.log('📦 Preset change requested:', globals.preset);
1620
-
1621
- // Store preset selection for persistence
1848
+ } else {
1622
1849
  try {
1623
- sessionStorage.setItem('storybook-pds-preset', globals.preset);
1624
- localStorage.setItem('storybook-pds-preset', globals.preset);
1625
- console.log('💾 Preset stored in storage');
1626
- } catch (e) {
1627
- console.warn('⚠️ Failed to store preset:', e);
1628
- }
1629
-
1630
- // Load preset from PDS presets and create new designer
1631
- console.log('📥 Importing pds-config...');
1632
- const configModule = await import('../../../src/js/pds-core/pds-config.js');
1633
- console.log(' Config module loaded:', configModule);
1634
-
1635
- const { presets } = configModule;
1636
- const presetId = globals.preset;
1637
- const presetConfig = presets[presetId];
1638
-
1639
- console.log('📋 Available presets:', Object.keys(presets));
1640
- console.log('🔍 Looking for preset:', presetId);
1641
- console.log(' Found preset config:', presetConfig ? 'yes' : 'no');
1642
-
1643
- if (presetConfig) {
1644
- console.log(`🎨 Applying preset: ${presetConfig.name || presetId}`);
1645
- console.log('📝 Preset config:', presetConfig);
1646
-
1647
- // Create new designer with preset config (same as pds-config-form does)
1648
- const generatorOptions = {
1649
- design: structuredClone(presetConfig),
1650
- log: (...args) => console.log('🟦 [Generator]', ...args)
1651
- };
1652
- const storedTheme = PDS.theme || null;
1653
- if (storedTheme) {
1654
- generatorOptions.theme = storedTheme;
1655
- console.log('🌙 Applying stored theme:', storedTheme);
1850
+ console.log('📦 Preset change requested:', globals.preset);
1851
+
1852
+ try {
1853
+ sessionStorage.setItem('storybook-pds-preset', globals.preset);
1854
+ localStorage.setItem('storybook-pds-preset', globals.preset);
1855
+ console.log('💾 Preset stored in storage');
1856
+ } catch (e) {
1857
+ console.warn('⚠️ Failed to store preset:', e);
1858
+ }
1859
+
1860
+ console.log('📥 Importing pds-config...');
1861
+ const configModule = await import('../../../src/js/pds-core/pds-config.js');
1862
+ console.log('✅ Config module loaded:', configModule);
1863
+
1864
+ const { presets } = configModule;
1865
+ const presetId = globals.preset;
1866
+ const presetConfig = presets[presetId];
1867
+
1868
+ console.log('📋 Available presets:', Object.keys(presets));
1869
+ console.log('🔍 Looking for preset:', presetId);
1870
+ console.log('✅ Found preset config:', presetConfig ? 'yes' : 'no');
1871
+
1872
+ if (presetConfig) {
1873
+ console.log(`🎨 Applying preset: ${presetConfig.name || presetId}`);
1874
+ console.log('📝 Preset config:', presetConfig);
1875
+
1876
+ const generatorOptions = {
1877
+ design: clonePresetDesign(presetConfig),
1878
+ log: (...args) => console.log('🟦 [Generator]', ...args)
1879
+ };
1880
+ const storedTheme = PDS.theme || null;
1881
+ if (storedTheme) {
1882
+ generatorOptions.theme = storedTheme;
1883
+ console.log('🌙 Applying stored theme:', storedTheme);
1884
+ }
1885
+
1886
+ console.log('🏗️ Creating new Generator...');
1887
+ const newDesigner = new Generator(generatorOptions);
1888
+ console.log('✅ Generator created');
1889
+
1890
+ console.log('🎨 Applying styles to document...');
1891
+ setLiveGenerator(newDesigner);
1892
+ await applyStyles(newDesigner);
1893
+ console.log('✅ Styles applied to document');
1894
+
1895
+ PDS.currentPreset = presetId;
1896
+ console.log(`✅✅✅ Preset applied successfully: ${presetConfig.name || presetId}`);
1897
+ } else {
1898
+ console.error(`❌ Preset not found: ${presetId}`);
1899
+ console.error('❌ Available presets:', Object.keys(presets));
1656
1900
  }
1657
-
1658
- console.log('🏗️ Creating new Generator...');
1659
- const newDesigner = new Generator(generatorOptions);
1660
- console.log('✅ Generator created');
1661
-
1662
- console.log('🎨 Applying styles to document...');
1663
- setLiveGenerator(newDesigner);
1664
- await applyStyles(newDesigner);
1665
- console.log('✅ Styles applied to document');
1666
-
1667
- // Update global reference
1668
- PDS.currentPreset = presetId;
1669
-
1670
- console.log(`✅✅✅ Preset applied successfully: ${presetConfig.name || presetId}`);
1671
- } else {
1672
- console.error(`❌ Preset not found: ${presetId}`);
1673
- console.error('❌ Available presets:', Object.keys(presets));
1901
+ } catch (err) {
1902
+ console.error('❌❌❌ Failed to apply preset:', err);
1903
+ console.error('❌ Stack trace:', err.stack);
1674
1904
  }
1675
- } catch (err) {
1676
- console.error('❌❌❌ Failed to apply preset:', err);
1677
- console.error('❌ Stack trace:', err.stack);
1905
+ }
1906
+ }
1907
+
1908
+ if (globals?.locale) {
1909
+ const requestedLocale = resolveSupportedLocale(globals.locale, storybookLocales, defaultStorybookLocale);
1910
+ if (requestedLocale) {
1911
+ console.log('🌍 Locale change requested:', requestedLocale);
1912
+ applyStorybookLocale(requestedLocale, { persist: true });
1678
1913
  }
1679
1914
  }
1680
1915
  }
@@ -6,10 +6,12 @@
6
6
  */
7
7
 
8
8
  export {
9
+ SHIKI_CODE_THEME,
9
10
  loadShiki,
10
11
  highlight,
11
12
  renderCodeBlock,
12
13
  getCurrentTheme,
13
14
  escapeHtml,
14
- preloadShiki
15
+ preloadShiki,
16
+ ensureSharedShikiStyles
15
17
  } from '../stories/utils/shiki.js';