@juspay/svelte-ui-components 4.27.5 → 4.28.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 (164) hide show
  1. package/README.md +140 -36
  2. package/dist/Animations/ModalAnimation.svelte +15 -1
  3. package/dist/Animations/OverlayAnimation.svelte +7 -1
  4. package/dist/AreaChart/AreaChart.svelte +366 -85
  5. package/dist/AspectRatio/AspectRatio.svelte +51 -0
  6. package/dist/AspectRatio/AspectRatio.svelte.d.ts +3 -0
  7. package/dist/AspectRatio/properties.d.ts +27 -0
  8. package/dist/AspectRatio/properties.js +1 -0
  9. package/dist/Banner/Banner.svelte +10 -4
  10. package/dist/Banner/properties.d.ts +8 -0
  11. package/dist/BarChart/BarChart.svelte +156 -49
  12. package/dist/Book/Book.svelte +14 -1
  13. package/dist/BrandLoader/BrandLoader.svelte +76 -12
  14. package/dist/Button/Button.svelte +56 -11
  15. package/dist/Calendar/Calendar.svelte +88 -61
  16. package/dist/Card/Card.svelte +1 -1
  17. package/dist/Carousel/Carousel.svelte +6 -3
  18. package/dist/ChatComposer/ChatComposer.svelte +54 -4
  19. package/dist/ChatComposer/dictationState.d.ts +15 -0
  20. package/dist/ChatComposer/dictationState.js +9 -0
  21. package/dist/ChatComposer/properties.d.ts +28 -1
  22. package/dist/ChatMessage/ChatMessage.svelte +27 -1
  23. package/dist/CheckListItem/CheckListItem.svelte +3 -3
  24. package/dist/Checkbox/Checkbox.svelte +84 -3
  25. package/dist/Checkbox/properties.d.ts +45 -13
  26. package/dist/ChipInput/ChipInput.svelte +70 -3
  27. package/dist/ChipInput/properties.d.ts +16 -0
  28. package/dist/Choicebox/Choicebox.svelte +156 -1
  29. package/dist/Choicebox/group.d.ts +63 -0
  30. package/dist/Choicebox/group.js +127 -0
  31. package/dist/Choicebox/properties.d.ts +46 -0
  32. package/dist/ColorPicker/ColorPicker.svelte +169 -20
  33. package/dist/ColorPicker/properties.d.ts +16 -0
  34. package/dist/Combobox/Combobox.svelte +87 -25
  35. package/dist/Combobox/properties.d.ts +23 -0
  36. package/dist/CommandMenu/CommandMenu.svelte +27 -11
  37. package/dist/ContextMenu/ContextMenu.svelte +31 -37
  38. package/dist/DateRangePicker/DateRangePicker.svelte +171 -73
  39. package/dist/DeltaIndicator/DeltaIndicator.svelte +3 -3
  40. package/dist/Draggable/Draggable.svelte +12 -7
  41. package/dist/DualAxisBarChart/DualAxisBarChart.svelte +11 -4
  42. package/dist/EmptyState/EmptyState.svelte +1 -1
  43. package/dist/FileDropzoneTrigger/FileDropzoneTrigger.svelte +1 -1
  44. package/dist/FileInput/FileInput.svelte +50 -1
  45. package/dist/FileInput/properties.d.ts +7 -0
  46. package/dist/FunnelChart/FunnelChart.svelte +40 -12
  47. package/dist/FunnelChart/properties.d.ts +7 -1
  48. package/dist/Gallery/Gallery.svelte +20 -13
  49. package/dist/Gallery/properties.d.ts +8 -0
  50. package/dist/GridItem/GridItem.svelte +31 -1
  51. package/dist/HITL/HITL.svelte +35 -9
  52. package/dist/Icon/Icon.svelte +19 -3
  53. package/dist/Input/Input.svelte +24 -10
  54. package/dist/Input/properties.d.ts +37 -1
  55. package/dist/InputButton/InputButton.svelte +86 -11
  56. package/dist/InputButton/properties.d.ts +10 -1
  57. package/dist/Label/Label.svelte +54 -0
  58. package/dist/Label/Label.svelte.d.ts +3 -0
  59. package/dist/Label/properties.d.ts +26 -0
  60. package/dist/Label/properties.js +1 -0
  61. package/dist/LineChart/LineChart.svelte +385 -94
  62. package/dist/ListItem/ListItem.svelte +121 -15
  63. package/dist/Loader/Loader.svelte +22 -2
  64. package/dist/LoadingDots/LoadingDots.svelte +21 -0
  65. package/dist/MediaUpload/MediaUpload.svelte +13 -3
  66. package/dist/Menu/Menu.svelte +56 -28
  67. package/dist/Modal/Modal.svelte +77 -42
  68. package/dist/Pagination/Pagination.svelte +9 -2
  69. package/dist/Phone/Phone.svelte +4 -0
  70. package/dist/PieChart/PieChart.svelte +282 -38
  71. package/dist/PieChart/properties.d.ts +9 -0
  72. package/dist/Pill/Pill.svelte +14 -5
  73. package/dist/Progress/Progress.svelte +20 -0
  74. package/dist/Radio/Radio.svelte +58 -1
  75. package/dist/Radio/properties.d.ts +23 -0
  76. package/dist/RatingGroup/RatingGroup.svelte +283 -0
  77. package/dist/RatingGroup/RatingGroup.svelte.d.ts +4 -0
  78. package/dist/RatingGroup/properties.d.ts +73 -0
  79. package/dist/RatingGroup/properties.js +1 -0
  80. package/dist/RelativeTime/RelativeTime.svelte +1 -1
  81. package/dist/SankeyChart/SankeyChart.svelte +272 -50
  82. package/dist/SankeyChart/properties.d.ts +9 -0
  83. package/dist/Scroller/Scroller.svelte +37 -2
  84. package/dist/Select/Select.svelte +166 -46
  85. package/dist/Select/properties.d.ts +7 -0
  86. package/dist/Separator/Separator.svelte +48 -0
  87. package/dist/Separator/Separator.svelte.d.ts +3 -0
  88. package/dist/Separator/properties.d.ts +22 -0
  89. package/dist/Separator/properties.js +1 -0
  90. package/dist/Sheet/Sheet.svelte +60 -21
  91. package/dist/Shimmer/Shimmer.svelte +15 -0
  92. package/dist/Slider/Slider.svelte +87 -6
  93. package/dist/Slider/properties.d.ts +26 -0
  94. package/dist/Snippet/Snippet.svelte +4 -0
  95. package/dist/Snippet/copyState.svelte.d.ts +13 -1
  96. package/dist/Snippet/copyState.svelte.js +27 -1
  97. package/dist/Snippet/properties.d.ts +7 -0
  98. package/dist/SoundKit/SoundKit.js +9 -8
  99. package/dist/SplitInput/SplitInput.svelte +68 -2
  100. package/dist/SplitInput/properties.d.ts +23 -0
  101. package/dist/StatCard/StatCard.svelte +6 -6
  102. package/dist/Status/Status.svelte +2 -2
  103. package/dist/Stepper/Step.svelte +19 -6
  104. package/dist/Stepper/Stepper.svelte +108 -35
  105. package/dist/Table/BuiltinCell.svelte +2 -2
  106. package/dist/Table/Table.svelte +373 -55
  107. package/dist/Table/properties.d.ts +134 -3
  108. package/dist/Tabs/Tabs.svelte +263 -65
  109. package/dist/Tabs/properties.d.ts +23 -0
  110. package/dist/TaskList/TaskList.svelte +14 -5
  111. package/dist/ThemeSwitcher/ThemeSwitcher.svelte +23 -0
  112. package/dist/ThinkingIndicator/ThinkingIndicator.svelte +13 -5
  113. package/dist/Toast/Toast.svelte +27 -2
  114. package/dist/Toggle/Toggle.svelte +79 -7
  115. package/dist/Toggle/Toggle.svelte.d.ts +1 -1
  116. package/dist/Toggle/properties.d.ts +30 -7
  117. package/dist/ToolCallLog/ToolCallLog.svelte +59 -21
  118. package/dist/ToolCallLog/properties.d.ts +10 -0
  119. package/dist/Toolbar/Toolbar.svelte +1 -1
  120. package/dist/Tooltip/Tooltip.svelte +20 -2
  121. package/dist/Tooltip/tooltip-action.js +39 -4
  122. package/dist/TypewriterText/TypewriterText.svelte +34 -2
  123. package/dist/TypewriterText/properties.d.ts +18 -5
  124. package/dist/_chart/ChartContainer.svelte +12 -0
  125. package/dist/_chart/ChartTooltip.svelte +18 -4
  126. package/dist/_chart/Legend.svelte +21 -0
  127. package/dist/_chart/Legend.svelte.d.ts +15 -0
  128. package/dist/_chart/geometry.d.ts +54 -1
  129. package/dist/_chart/geometry.js +122 -14
  130. package/dist/_chart/interactions.d.ts +5 -1
  131. package/dist/_chart/interactions.js +9 -5
  132. package/dist/_chart/scales.js +16 -0
  133. package/dist/_chart/temporal.d.ts +45 -0
  134. package/dist/_chart/temporal.js +116 -0
  135. package/dist/_field/description.d.ts +50 -0
  136. package/dist/_field/description.js +51 -0
  137. package/dist/_interaction/dismissal.d.ts +67 -0
  138. package/dist/_interaction/dismissal.js +137 -0
  139. package/dist/_interaction/focus.d.ts +73 -0
  140. package/dist/_interaction/focus.js +143 -0
  141. package/dist/assets/star.svg +5 -0
  142. package/dist/index.d.ts +13 -1
  143. package/dist/index.js +21 -1
  144. package/dist/reduced-motion.svelte.d.ts +37 -0
  145. package/dist/reduced-motion.svelte.js +44 -0
  146. package/dist/styles/theme-dark.css +778 -0
  147. package/dist/types.d.ts +4 -2
  148. package/dist/utils.d.ts +62 -1
  149. package/dist/utils.js +80 -21
  150. package/dist-codemod/{bin.js → codemod/bin.js} +13 -2
  151. package/dist-codemod/{cli.js → codemod/cli.js} +48 -3
  152. package/dist-codemod/codemod/migrate-audit.js +395 -0
  153. package/dist-codemod/codemod/migration-assets/legacy-display.css +120 -0
  154. package/dist-codemod/codemod/migration-assets/legacy-palette.css +106 -0
  155. package/dist-codemod/codemod/migration-assets/wc-display.json +492 -0
  156. package/dist-codemod/migrate/analyze.js +804 -0
  157. package/dist-codemod/migrate/chart-tooltip-selector.js +301 -0
  158. package/dist-wc/index.js +13992 -4323
  159. package/package.json +13 -6
  160. package/dist/Modal/focus-trap.d.ts +0 -42
  161. package/dist/Modal/focus-trap.js +0 -57
  162. /package/dist-codemod/{legacy-pairs.js → codemod/legacy-pairs.js} +0 -0
  163. /package/dist-codemod/{transform.js → codemod/transform.js} +0 -0
  164. /package/dist-codemod/{wc-children.js → codemod/wc-children.js} +0 -0
@@ -0,0 +1,395 @@
1
+ import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';
2
+ import { dirname, join, relative, resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { parseArgs } from 'node:util';
5
+ import { analyzeStylesheet, analyzeSvelte, LIBRARY } from "../migrate/analyze.js";
6
+ import { planSelectorRewrites } from "../migrate/chart-tooltip-selector.js";
7
+ import { SKIPPED_DIRECTORIES } from "./cli.js";
8
+ /**
9
+ * Runs the 4.28.0 breaking-change audit `npm run migrate` runs, from the
10
+ * PUBLISHED `sui-codemod` binary against a consumer project that only has
11
+ * this package installed -- never a repo clone. `npm run migrate` (see
12
+ * scripts/migrate/cli.ts) is not itself shippable: it reads this library's
13
+ * OWN `src/wc/components` and git history, neither of which exist in
14
+ * node_modules. This file reuses its detectors (`analyzeSvelte`/
15
+ * `analyzeStylesheet`) unmodified and replaces only the one input that
16
+ * required repo-only sources -- `AnalyzeContext.wcComponents` -- with a
17
+ * reader for `wc-display.json`, a plain data file `generate-migration-assets.ts`
18
+ * derives during `build:codemod` and ships inside `dist-codemod`. See that
19
+ * file for what it writes and why: `wc-display.json`, `legacy-display.css`,
20
+ * `legacy-palette.css`.
21
+ *
22
+ * Deliberately narrower than `npm run migrate`: it does not reproduce that
23
+ * script's package.json/svelte-peer version bump (`analyzeManifest`) --
24
+ * that is a different, repo-version-coupled feature (pin/bump this
25
+ * library's own dependency range), not one of the seven breaking changes
26
+ * this migration guide documents. What ships here is the audit for those
27
+ * seven, which is the part a consumer with only the published package can
28
+ * never otherwise reach.
29
+ */
30
+ // ------------------------------------------------------------- wc-display.json
31
+ const MIGRATION_ASSETS_DIRNAME = 'migration-assets';
32
+ const WC_DISPLAY_FILENAME = 'wc-display.json';
33
+ export const LEGACY_DISPLAY_CSS_FILENAME = 'legacy-display.css';
34
+ export const LEGACY_PALETTE_CSS_FILENAME = 'legacy-palette.css';
35
+ /**
36
+ * The directory `generate-migration-assets.ts` writes into, resolved off
37
+ * THIS module's own compiled location rather than `process.cwd()` -- so it
38
+ * still finds `dist-codemod/migration-assets` when this module has been
39
+ * compiled to `dist-codemod/migrate-audit.js` and invoked from anywhere.
40
+ * Run against the uncompiled `.ts` source (as the tests below do without an
41
+ * explicit `assetsDir` override) it resolves to a sibling directory that
42
+ * does not exist -- which is the correct answer, not a bug: this module
43
+ * has no other way to find build output that was never produced, and
44
+ * `loadWcDisplay` below turns that into an honest "missing" result rather
45
+ * than a guess.
46
+ */
47
+ function defaultAssetsDir() {
48
+ return join(dirname(fileURLToPath(import.meta.url)), MIGRATION_ASSETS_DIRNAME);
49
+ }
50
+ /** Same no-assertion narrowing `analyze.ts`'s own `asRecord` uses: copies known-present keys onto a fresh object rather than casting. */
51
+ function asRecord(value) {
52
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
53
+ return null;
54
+ }
55
+ const record = {};
56
+ for (const key of Object.keys(value)) {
57
+ Object.defineProperty(record, key, {
58
+ value: Reflect.get(value, key),
59
+ enumerable: true,
60
+ writable: true,
61
+ configurable: true
62
+ });
63
+ }
64
+ return record;
65
+ }
66
+ /**
67
+ * `null`, never a boolean, on anything that fails to match -- the fail-closed
68
+ * rule `host-display-compat.ts`'s own `parseHostDisplay` documents: a shim
69
+ * silently missing an entry looks exactly as complete as one that isn't, and
70
+ * the same is true of a context built from a partially-invalid file. One bad
71
+ * entry invalidates the whole read; see `loadWcDisplay`.
72
+ */
73
+ function asWcDisplayEntry(value) {
74
+ const record = asRecord(value);
75
+ if (record === null) {
76
+ return null;
77
+ }
78
+ const { tag, property } = record;
79
+ const wcDefault = record.default;
80
+ if (typeof tag !== 'string' || tag.length === 0) {
81
+ return null;
82
+ }
83
+ if (typeof property !== 'string' || property.length === 0) {
84
+ return null;
85
+ }
86
+ if (wcDefault !== 'block' && wcDefault !== 'inline-block') {
87
+ return null;
88
+ }
89
+ return { tag, property, default: wcDefault };
90
+ }
91
+ /**
92
+ * Reads and validates `wc-display.json`, distinguishing "the file is absent"
93
+ * from "the file is present but unreadable" from "ok" -- collapsing either
94
+ * failure to an empty component list would make `host-display-inline` and
95
+ * `chart-min-width` report zero findings exactly as a genuinely clean project
96
+ * would, which is the one thing this audit must not do silently.
97
+ */
98
+ export function loadWcDisplay(path) {
99
+ if (!existsSync(path)) {
100
+ return { status: 'missing', path };
101
+ }
102
+ let parsed;
103
+ try {
104
+ parsed = JSON.parse(readFileSync(path, 'utf8'));
105
+ }
106
+ catch (error) {
107
+ return {
108
+ status: 'invalid',
109
+ path,
110
+ reason: `not valid JSON (${error instanceof Error ? error.message : String(error)})`
111
+ };
112
+ }
113
+ if (!Array.isArray(parsed)) {
114
+ return { status: 'invalid', path, reason: 'expected a JSON array at the top level' };
115
+ }
116
+ const entries = [];
117
+ for (const [index, item] of parsed.entries()) {
118
+ const entry = asWcDisplayEntry(item);
119
+ if (entry === null) {
120
+ return {
121
+ status: 'invalid',
122
+ path,
123
+ reason: `entry ${index} is missing a valid tag/property/default`
124
+ };
125
+ }
126
+ entries.push(entry);
127
+ }
128
+ // An empty array is not a valid manifest, it is a broken build that parsed.
129
+ // Accepting it made the audit print `wc-display.json: ok (0 component(s))`
130
+ // and then silently run with `host-display-inline` and `chart-min-width`
131
+ // disabled -- a clean report that had checked two fewer things than it
132
+ // claimed, which is indistinguishable from a project that has neither
133
+ // problem. `collectWcDisplayEntries` already refuses to WRITE an empty
134
+ // manifest for the same reason; this is the reading half of that rule.
135
+ if (entries.length === 0) {
136
+ return {
137
+ status: 'invalid',
138
+ path,
139
+ reason: 'contains no components — the build that produced it was broken'
140
+ };
141
+ }
142
+ return { status: 'ok', path, entries };
143
+ }
144
+ /**
145
+ * Recovers each entry's `component` (the wrapped Svelte component's PascalCase
146
+ * name -- `chart-min-width`'s "*Chart" filter and `inputbutton-mandatory`'s
147
+ * "InputButton" spelling both key off it, see `analyzeSvelte`) from `tag`
148
+ * alone, since `wc-display.json` does not carry it (see `WcDisplayEntry`
149
+ * above). This is the one place this file re-derives something `readWcComponents`
150
+ * also derives, rather than only relaying data across the wc-display.json
151
+ * boundary -- justified because the boundary's schema does not (yet) carry the
152
+ * field, and bounded because it is checked against real output below rather
153
+ * than trusted blind: every `sui-*` wrapper in this checkout follows
154
+ * `sui-<kebab-case>` <-> `<PascalCase>`, EXCEPT one (`sui-hitl` -> `HITL`,
155
+ * which this produces as `Hitl`) -- and that exception is neither a `*Chart`
156
+ * name nor `InputButton`, so it cannot affect either detector that reads
157
+ * `component`. A future acronym-named Chart component or a renamed
158
+ * InputButton would need this fixed at the source instead: threading
159
+ * `component` through `HostDisplayEntry` (derivable there from `file`'s own
160
+ * basename, exactly as `readWcComponents` derives it) and into
161
+ * `WcDisplayAsset`/`wc-display.json` itself, which this file cannot do --
162
+ * `generate-migration-assets.ts` and `host-display-compat.ts` are not its own.
163
+ */
164
+ function pascalCaseFromTag(tag) {
165
+ return tag
166
+ .replace(/^sui-/, '')
167
+ .split('-')
168
+ .filter((segment) => segment.length > 0)
169
+ .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
170
+ .join('');
171
+ }
172
+ export function wcComponentsFrom(entries) {
173
+ return entries.map((entry) => ({
174
+ component: pascalCaseFromTag(entry.tag),
175
+ tag: entry.tag,
176
+ display: entry.default
177
+ }));
178
+ }
179
+ function shimStatus(assetsDir, filename) {
180
+ const path = join(assetsDir, filename);
181
+ return { filename, present: existsSync(path), path };
182
+ }
183
+ /**
184
+ * `.svelte` and `.css` files under `root`, skipping the same directories the
185
+ * prop-rename transform skips (`SKIPPED_DIRECTORIES`, imported from `cli.ts`
186
+ * rather than redeclared, so the two commands can never drift apart on what
187
+ * "skip node_modules et al." means). Not `scripts/migrate/cli.ts`'s own
188
+ * `projectFiles` -- that function is module-private there and reading a
189
+ * consumer's files is a three-line walk, not detection logic, so writing it
190
+ * here is not the kind of duplication the analyzers themselves must avoid.
191
+ */
192
+ function consumerFiles(root) {
193
+ const svelte = [];
194
+ const css = [];
195
+ const visit = (dir) => {
196
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
197
+ if (entry.isDirectory()) {
198
+ if (!SKIPPED_DIRECTORIES.has(entry.name)) {
199
+ visit(join(dir, entry.name));
200
+ }
201
+ continue;
202
+ }
203
+ if (entry.name.endsWith('.svelte')) {
204
+ svelte.push(join(dir, entry.name));
205
+ }
206
+ else if (entry.name.endsWith('.css')) {
207
+ css.push(join(dir, entry.name));
208
+ }
209
+ }
210
+ };
211
+ visit(root);
212
+ return { svelte, css };
213
+ }
214
+ const MIGRATE_USAGE = [
215
+ 'Usage: sui-codemod migrate [--dry-run] <consumer path>',
216
+ ' (inside this repository: node scripts/codemod/cli.ts migrate ...)',
217
+ '',
218
+ `Audits a consumer project against the seven breaking changes in ${LIBRARY} 4.28.0:`,
219
+ "InputButton's mandatory prop now also setting native required; a sui-*",
220
+ "custom element used where the browser's old implicit inline mattered; a",
221
+ 'chart rendered into a parent narrower than its new 160px floor; the',
222
+ 'renamed chart tooltip slot selector; and sui-chat-composer’s recording',
223
+ "attribute, which no longer reflects. See scripts/migrate/README.md's",
224
+ 'reason table -- the same detectors run here as in `npm run migrate`.',
225
+ '',
226
+ 'The chart tooltip selector rewrite is mechanical, so it is also applied',
227
+ 'directly (like the default prop-rename command): every other finding is',
228
+ 'reported for review, never rewritten automatically.',
229
+ '',
230
+ ' --dry-run print the tooltip selector rewrite as a diff without writing it',
231
+ ' --help show this help',
232
+ '',
233
+ 'Also reports whether this install shipped the two compatibility',
234
+ `stylesheets the migration guide describes -- ${LEGACY_DISPLAY_CSS_FILENAME} and`,
235
+ `${LEGACY_PALETTE_CSS_FILENAME} -- by name, so a consumer knows to look for them`,
236
+ 'instead of generating either by hand.'
237
+ ].join('\n');
238
+ function emptySummary(exitCode, wcDisplay) {
239
+ return {
240
+ exitCode,
241
+ filesScanned: 0,
242
+ cssFilesScanned: 0,
243
+ findings: [],
244
+ wcDisplay,
245
+ rewrites: [],
246
+ applied: false
247
+ };
248
+ }
249
+ const UNRESOLVED_WC_DISPLAY = { status: 'missing', path: '' };
250
+ function printLineDiff(file, before, after, log) {
251
+ const oldLines = before.split('\n');
252
+ const newLines = after.split('\n');
253
+ log(`--- ${file}`);
254
+ if (oldLines.length !== newLines.length) {
255
+ log(' (line counts differ; showing full replacement)');
256
+ for (const line of oldLines) {
257
+ log(`- ${line}`);
258
+ }
259
+ for (const line of newLines) {
260
+ log(`+ ${line}`);
261
+ }
262
+ return;
263
+ }
264
+ oldLines.forEach((oldLine, index) => {
265
+ const newLine = newLines.at(index) ?? '';
266
+ if (oldLine !== newLine) {
267
+ log(`@@ ${file}:${index + 1}`);
268
+ log(`- ${oldLine}`);
269
+ log(`+ ${newLine}`);
270
+ }
271
+ });
272
+ }
273
+ export function runMigrateAudit(argv, log, options = {}) {
274
+ let parsed;
275
+ try {
276
+ parsed = parseArgs({
277
+ args: [...argv],
278
+ options: {
279
+ 'dry-run': { type: 'boolean' },
280
+ help: { type: 'boolean' }
281
+ },
282
+ allowPositionals: true,
283
+ strict: true
284
+ });
285
+ }
286
+ catch (error) {
287
+ log(error instanceof Error ? error.message : String(error));
288
+ log(MIGRATE_USAGE);
289
+ return emptySummary(2, UNRESOLVED_WC_DISPLAY);
290
+ }
291
+ if (parsed.values.help === true) {
292
+ log(MIGRATE_USAGE);
293
+ return emptySummary(0, UNRESOLVED_WC_DISPLAY);
294
+ }
295
+ if (parsed.positionals.length !== 1) {
296
+ log(MIGRATE_USAGE);
297
+ return emptySummary(2, UNRESOLVED_WC_DISPLAY);
298
+ }
299
+ const root = resolve(parsed.positionals[0]);
300
+ if (!existsSync(root) || !statSync(root).isDirectory()) {
301
+ log(`error: ${root} is not a directory`);
302
+ return emptySummary(2, UNRESOLVED_WC_DISPLAY);
303
+ }
304
+ const assetsDir = options.assetsDir ?? defaultAssetsDir();
305
+ const wcDisplay = loadWcDisplay(join(assetsDir, WC_DISPLAY_FILENAME));
306
+ log(`sui-codemod migrate: auditing ${root} against ${LIBRARY} 4.28.0`);
307
+ log('');
308
+ let context;
309
+ if (wcDisplay.status === 'ok') {
310
+ context = { wcComponents: wcComponentsFrom(wcDisplay.entries) };
311
+ log(`wc-display.json: ok (${wcDisplay.entries.length} component(s) at ${wcDisplay.path})`);
312
+ }
313
+ else if (wcDisplay.status === 'missing') {
314
+ context = { wcComponents: [] };
315
+ log(`wc-display.json: NOT FOUND at ${wcDisplay.path}`);
316
+ log(' host-display-inline and chart-min-width could not be audited -- a clean result below');
317
+ log(' does not mean this project is clear of them, only that this run could not look. This');
318
+ log(' file ships inside dist-codemod; reinstall the package if it is missing.');
319
+ }
320
+ else {
321
+ context = { wcComponents: [] };
322
+ log(`wc-display.json: INVALID at ${wcDisplay.path} -- ${wcDisplay.reason}`);
323
+ log(' host-display-inline and chart-min-width could not be audited -- a clean result below');
324
+ log(' does not mean this project is clear of them, only that this run could not look.');
325
+ }
326
+ log('');
327
+ const files = consumerFiles(root);
328
+ const svelteFindings = files.svelte.flatMap((file) => analyzeSvelte(readFileSync(file, 'utf8'), relative(root, file), context));
329
+ const cssFindings = files.css.flatMap((file) => analyzeStylesheet(readFileSync(file, 'utf8'), relative(root, file)));
330
+ const findings = [...svelteFindings, ...cssFindings];
331
+ for (const finding of findings) {
332
+ log(`${finding.reason} ${finding.file}:${finding.line}`);
333
+ log(` ${finding.detail}`);
334
+ }
335
+ if (findings.length === 0) {
336
+ log(`No findings across ${files.svelte.length} .svelte and ${files.css.length} .css file(s).`);
337
+ }
338
+ log('');
339
+ // The one finding above that is mechanically fixable: applied directly
340
+ // under sui-codemod's own --dry-run flag, the same way the default
341
+ // prop-rename command applies its rewrite -- never chart-tooltip-selector.ts's
342
+ // own --apply, which this command does not expose.
343
+ const dryRun = parsed.values['dry-run'] === true;
344
+ const rewrites = planSelectorRewrites(root);
345
+ for (const rewrite of rewrites) {
346
+ const parts = [
347
+ rewrite.selectorCount > 0 ? `${rewrite.selectorCount} selector(s)` : '',
348
+ rewrite.scriptCount > 0 ? `${rewrite.scriptCount} querySelector string(s)` : ''
349
+ ].filter((part) => part.length > 0);
350
+ const relativeFile = relative(root, rewrite.file);
351
+ if (dryRun) {
352
+ const before = readFileSync(rewrite.file, 'utf8');
353
+ log(`[dry run] would rewrite ${relativeFile}: ${parts.join(', ')}`);
354
+ printLineDiff(relativeFile, before, rewrite.code, log);
355
+ }
356
+ else {
357
+ writeFileSync(rewrite.file, rewrite.code);
358
+ log(`rewrote ${relativeFile}: ${parts.join(', ')}`);
359
+ }
360
+ }
361
+ if (rewrites.length === 0) {
362
+ log('No .chart-tooltip-slot selector found to rewrite.');
363
+ }
364
+ log('');
365
+ const legacyDisplay = shimStatus(assetsDir, LEGACY_DISPLAY_CSS_FILENAME);
366
+ const legacyPalette = shimStatus(assetsDir, LEGACY_PALETTE_CSS_FILENAME);
367
+ log('Compatibility shims shipped with this install:');
368
+ log(` ${legacyDisplay.filename}: ${legacyDisplay.present ? `present at ${legacyDisplay.path}` : 'NOT FOUND'} -- restores the old implicit "inline" default host-display-inline findings above describe`);
369
+ log(` ${legacyPalette.filename}: ${legacyPalette.present ? `present at ${legacyPalette.path}` : 'NOT FOUND'} -- restores pre-contrast-pass colors; this audit has no detector for that change, review docs/MIGRATION_4.28.md`);
370
+ log('');
371
+ // Findings are computed before the rewrite runs, so on a non-dry run the
372
+ // tooltip selectors this command just FIXED are still sitting in that list.
373
+ // Reporting them as "needing review" sends a consumer to look at something
374
+ // that is already correct on disk, and — worse — makes a second run look
375
+ // like it changed nothing when it had nothing left to change. What remains
376
+ // is what the consumer still has to do by hand.
377
+ const rewrittenFiles = new Set(rewrites.map((rewrite) => relative(root, rewrite.file)));
378
+ const remaining = dryRun || rewrites.length === 0
379
+ ? findings
380
+ : findings.filter((finding) => finding.reason !== 'chart-tooltip-slot-selector' || !rewrittenFiles.has(finding.file));
381
+ const fixedCount = findings.length - remaining.length;
382
+ log(`scanned ${files.svelte.length} .svelte and ${files.css.length} .css file(s), ` +
383
+ `${remaining.length} finding(s) needing review` +
384
+ (fixedCount > 0 ? `, ${fixedCount} already fixed by this run` : '') +
385
+ `, ${rewrites.length} file(s) with an auto-fixable tooltip selector`);
386
+ return {
387
+ exitCode: 0,
388
+ filesScanned: files.svelte.length,
389
+ cssFilesScanned: files.css.length,
390
+ findings: remaining,
391
+ wcDisplay,
392
+ rewrites,
393
+ applied: !dryRun && rewrites.length > 0
394
+ };
395
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * COMPATIBILITY SHIM -- generated by scripts/migrate/host-display-compat.ts
3
+ * Regenerate: node scripts/migrate/host-display-compat.ts --out <path>
4
+ *
5
+ * Before this version, none of these custom elements declared a :host display rule, so an
6
+ * unknown element's browser default -- display: inline -- applied. This version gives each one
7
+ * an explicit ":host { display: var(--sui-<name>-display, <default>) }", which is a real layout
8
+ * change at an unchanged call site for any consumer who laid out around the old implicit inline.
9
+ *
10
+ * Each rule below pins that element's display custom property back to inline, restoring the
11
+ * exact pre-upgrade layout: drop this file in, confirm nothing moved, then delete rules
12
+ * one at a time as each call site is verified against the new default.
13
+ *
14
+ * DO NOT KEEP THIS FILE. Restoring the old implicit inline forever reintroduces the bug the
15
+ * :host rule fixed: a percentage-width child of an implicitly-inline host has no width to
16
+ * resolve against, so "width: 100%" inside one of these elements silently collapses. This
17
+ * stylesheet is a crutch for the migration window, not a permanent override.
18
+ */
19
+
20
+ /* components whose new default is `block` (87) */
21
+ sui-accordion { --sui-accordion-display: inline; }
22
+ sui-area-chart { --sui-area-chart-display: inline; }
23
+ sui-aspect-ratio { --sui-aspect-ratio-display: inline; }
24
+ sui-attachment-chip-row { --sui-attachment-chip-row-display: inline; }
25
+ sui-badge { --sui-badge-display: inline; }
26
+ sui-banner { --sui-banner-display: inline; }
27
+ sui-bar-chart { --sui-bar-chart-display: inline; }
28
+ sui-book { --sui-book-display: inline; }
29
+ sui-brand-loader { --sui-brand-loader-display: inline; }
30
+ sui-breadcrumb { --sui-breadcrumb-display: inline; }
31
+ sui-browser { --sui-browser-display: inline; }
32
+ sui-button { --sui-button-display: inline; }
33
+ sui-calendar { --sui-calendar-display: inline; }
34
+ sui-card { --sui-card-display: inline; }
35
+ sui-carousel { --sui-carousel-display: inline; }
36
+ sui-chat { --sui-chat-display: inline; }
37
+ sui-chat-bubble { --sui-chat-bubble-display: inline; }
38
+ sui-chat-composer { --sui-chat-composer-display: inline; }
39
+ sui-chat-header { --sui-chat-header-display: inline; }
40
+ sui-chat-message { --sui-chat-message-display: inline; }
41
+ sui-chat-message-list { --sui-chat-message-list-display: inline; }
42
+ sui-chat-tool-status { --sui-chat-tool-status-display: inline; }
43
+ sui-check-list-item { --sui-check-list-item-display: inline; }
44
+ sui-chip-input { --sui-chip-input-display: inline; }
45
+ sui-choicebox { --sui-choicebox-display: inline; }
46
+ sui-color-picker { --sui-color-picker-display: inline; }
47
+ sui-combobox { --sui-combobox-display: inline; }
48
+ sui-command-menu { --sui-command-menu-display: inline; }
49
+ sui-context-menu { --sui-context-menu-display: inline; }
50
+ sui-draggable { --sui-draggable-display: inline; }
51
+ sui-dual-axis-bar-chart { --sui-dual-axis-bar-chart-display: inline; }
52
+ sui-empty-state { --sui-empty-state-display: inline; }
53
+ sui-file-dropzone-trigger { --sui-file-dropzone-trigger-display: inline; }
54
+ sui-file-input { --sui-file-input-display: inline; }
55
+ sui-funnel-chart { --sui-funnel-chart-display: inline; }
56
+ sui-gallery { --sui-gallery-display: inline; }
57
+ sui-gauge { --sui-gauge-display: inline; }
58
+ sui-grid-item { --sui-grid-item-display: inline; }
59
+ sui-hitl { --sui-hitl-display: inline; }
60
+ sui-icon { --sui-icon-display: inline; }
61
+ sui-icon-stack { --sui-icon-stack-display: inline; }
62
+ sui-iframe-viewer { --sui-iframe-viewer-display: inline; }
63
+ sui-input { --sui-input-display: inline; }
64
+ sui-input-button { --sui-input-button-display: inline; }
65
+ sui-key-value { --sui-key-value-display: inline; }
66
+ sui-line-chart { --sui-line-chart-display: inline; }
67
+ sui-list-item { --sui-list-item-display: inline; }
68
+ sui-loader { --sui-loader-display: inline; }
69
+ sui-lottie-player { --sui-lottie-player-display: inline; }
70
+ sui-markdown-text { --sui-markdown-text-display: inline; }
71
+ sui-media-player { --sui-media-player-display: inline; }
72
+ sui-media-upload { --sui-media-upload-display: inline; }
73
+ sui-menu { --sui-menu-display: inline; }
74
+ sui-modal { --sui-modal-display: inline; }
75
+ sui-pagination { --sui-pagination-display: inline; }
76
+ sui-phone { --sui-phone-display: inline; }
77
+ sui-pie-chart { --sui-pie-chart-display: inline; }
78
+ sui-pill { --sui-pill-display: inline; }
79
+ sui-progress { --sui-progress-display: inline; }
80
+ sui-proportion-bar { --sui-proportion-bar-display: inline; }
81
+ sui-rating-group { --sui-rating-group-display: inline; }
82
+ sui-relative-time { --sui-relative-time-display: inline; }
83
+ sui-resizable { --sui-resizable-display: inline; }
84
+ sui-sankey-chart { --sui-sankey-chart-display: inline; }
85
+ sui-scroller { --sui-scroller-display: inline; }
86
+ sui-select { --sui-select-display: inline; }
87
+ sui-separator { --sui-separator-display: inline; }
88
+ sui-sheet { --sui-sheet-display: inline; }
89
+ sui-shimmer { --sui-shimmer-display: inline; }
90
+ sui-slider { --sui-slider-display: inline; }
91
+ sui-snippet { --sui-snippet-display: inline; }
92
+ sui-split-button { --sui-split-button-display: inline; }
93
+ sui-split-input { --sui-split-input-display: inline; }
94
+ sui-stat-card { --sui-stat-card-display: inline; }
95
+ sui-status { --sui-status-display: inline; }
96
+ sui-stepper { --sui-stepper-display: inline; }
97
+ sui-table { --sui-table-display: inline; }
98
+ sui-tabs { --sui-tabs-display: inline; }
99
+ sui-task-list { --sui-task-list-display: inline; }
100
+ sui-thinking-indicator { --sui-thinking-indicator-display: inline; }
101
+ sui-toast { --sui-toast-display: inline; }
102
+ sui-toggle { --sui-toggle-display: inline; }
103
+ sui-tool-call-log { --sui-tool-call-log-display: inline; }
104
+ sui-toolbar { --sui-toolbar-display: inline; }
105
+ sui-tooltip { --sui-tooltip-display: inline; }
106
+ sui-typewriter-text { --sui-typewriter-text-display: inline; }
107
+ sui-voice-orb { --sui-voice-orb-display: inline; }
108
+
109
+ /* components whose new default is `inline-block` (11) */
110
+ sui-avatar { --sui-avatar-display: inline; }
111
+ sui-chat-suggestions { --sui-chat-suggestions-display: inline; }
112
+ sui-checkbox { --sui-checkbox-display: inline; }
113
+ sui-date-range-picker { --sui-date-range-picker-display: inline; }
114
+ sui-delta-indicator { --sui-delta-indicator-display: inline; }
115
+ sui-img { --sui-img-display: inline; }
116
+ sui-keyboard-input { --sui-keyboard-input-display: inline; }
117
+ sui-label { --sui-label-display: inline; }
118
+ sui-loading-dots { --sui-loading-dots-display: inline; }
119
+ sui-radio { --sui-radio-display: inline; }
120
+ sui-theme-switcher { --sui-theme-switcher-display: inline; }
@@ -0,0 +1,106 @@
1
+ /*
2
+ * Legacy palette -- pins this library to its pre-AA contrast fallbacks.
3
+ *
4
+ * PR 598 ran a WCAG-AA contrast pass over src/lib that darkened the
5
+ * literal fallback of the custom properties below. A consumer who never
6
+ * overrode one of these tokens rendered the OLD colour at an unchanged
7
+ * call site, and this stylesheet restores exactly that -- nothing more.
8
+ *
9
+ * Several of the values restored here FAIL WCAG AA; that is why the pass
10
+ * changed them. Adopting the new defaults -- i.e. NOT loading this file --
11
+ * is the intended end state. This exists to make that change reviewable
12
+ * one property at a time, not to be a permanent fixture in a consumer
13
+ * build.
14
+ *
15
+ * 51 properties pinned below. 9 more could not be -- see the note at the end.
16
+ *
17
+ * Generated by scripts/migrate/legacy-palette.ts -- do not hand edit.
18
+ */
19
+ :root { --banner-link-color: #0099ff; } /* was the 4.27.x default */
20
+ :root { --calendar-day-name-color: #999999; } /* was the 4.27.x default */
21
+ :root { --calendar-disabled-color: #cccccc; } /* was the 4.27.x default */
22
+ :root { --calendar-outside-month-color: #cccccc; } /* was the 4.27.x default */
23
+ :root { --card-description-opacity: 0.6; } /* was the 4.27.x default */
24
+ :root { --chat-composer-placeholder-color: #a1a1aa; } /* was the 4.27.x default */
25
+ :root { --chat-message-link-color: #6d28d9; } /* was the 4.27.x default */
26
+ :root { --delta-indicator-negative-color: #e5484d; } /* was the 4.27.x default */
27
+ :root { --delta-indicator-neutral-color: #8a8a8a; } /* was the 4.27.x default */
28
+ :root { --delta-indicator-positive-color: #1a9d6f; } /* was the 4.27.x default */
29
+ :root { --drp-panel-background: inherit; } /* was the 4.27.x default */
30
+ :root { --empty-state-description-opacity: 0.6; } /* was the 4.27.x default */
31
+ :root { --field-group-label-color: #9ca3af; } /* was the 4.27.x default */
32
+ :root { --file-dropzone-trigger-caption-color: #64748b; } /* was the 4.27.x default */
33
+ :root { --hitl-approved-color: #16a34a; } /* was the 4.27.x default */
34
+ :root { --hitl-badge-color: #858585; } /* was the 4.27.x default */
35
+ :root { --hitl-description-color: #858585; } /* was the 4.27.x default */
36
+ :root { --hitl-param-label-color: #858585; } /* was the 4.27.x default */
37
+ :root { --input-char-count-color: #98a2b3; } /* was the 4.27.x default */
38
+ :root { --loader-text-color: white; } /* was the 4.27.x default */
39
+ :root { --media-upload-add-color: #6b7280; } /* was the 4.27.x default */
40
+ :root { --media-upload-add-hint-color: #9aa0a8; } /* was the 4.27.x default */
41
+ :root { --media-upload-counter-color: #8a8f98; } /* was the 4.27.x default */
42
+ :root { --pagination-button-color: #3a4550; } /* was the 4.27.x default */
43
+ :root { --pagination-load-more-color: #3a4550; } /* was the 4.27.x default */
44
+ :root { --pill-tone-muted-color: #6b7280; } /* was the 4.27.x default */
45
+ :root { --select-placeholder-color: #999999; } /* was the 4.27.x default */
46
+ :root { --separator-margin: 0px 12px 0px 12px; } /* was the 4.27.x default */
47
+ :root { --statcard-breakdown-label-color: #9ca3af; } /* was the 4.27.x default */
48
+ :root { --statcard-delta-positive-color: #16a34a; } /* was the 4.27.x default */
49
+ :root { --statcard-row-additional-color: #9ca3af; } /* was the 4.27.x default */
50
+ :root { --statcard-subtitle-color: #9ca3af; } /* was the 4.27.x default */
51
+ :root { --statcard-value-warning-color: #f59e0b; } /* was the 4.27.x default */
52
+ :root { --step-index-container-background-color: #798fa5cc; } /* was the 4.27.x default */
53
+ :root { --step-index-container-completed-background-color: #24aa5a; } /* was the 4.27.x default */
54
+ :root { --step-text-color: #798fa5cc; } /* was the 4.27.x default */
55
+ :root { --step-text-completed-color: #24aa5a; } /* was the 4.27.x default */
56
+ :root { --stepper-separator-background-image-completed-color: #24aa5a; } /* was the 4.27.x default */
57
+ :root { --table-cell-thumb-placeholder-color: #6b7280; } /* was the 4.27.x default */
58
+ :root { --table-search-placeholder-color: #9ca3af; } /* was the 4.27.x default */
59
+ :root { --table-title-color: #111827; } /* was the 4.27.x default */
60
+ :root { --table-trend-up-color: #16a34a; } /* was the 4.27.x default */
61
+ :root { --tabs-active-color: #1a73e8; } /* was the 4.27.x default */
62
+ :root { --task-list-pending-opacity: 0.55; } /* was the 4.27.x default */
63
+ :root { --task-list-secondary-color: #9a9a9a; } /* was the 4.27.x default */
64
+ :root { --thinking-indicator-detail-color: #bebebe; } /* was the 4.27.x default */
65
+ :root { --thinking-indicator-elapsed-color: #9a9a9a; } /* was the 4.27.x default */
66
+ :root { --thinking-indicator-trace-secondary-color: #9a9a9a; } /* was the 4.27.x default */
67
+ :root { --tool-call-log-error-color: #c93f38; } /* was the 4.27.x default */
68
+ :root { --tool-call-log-meta-color: #9a9a9a; } /* was the 4.27.x default */
69
+ :root { --tool-call-log-removed-color: #c93f38; } /* was the 4.27.x default */
70
+
71
+ /*
72
+ * Not literal pins -- these properties did not exist on the selectors
73
+ * below at all before this change, so each one rendered whatever value
74
+ * its ANCESTOR supplied, not a value from this library. There is no old
75
+ * literal to restore, only inheritance to put back, which is why the
76
+ * rule shape differs from the pins above.
77
+ *
78
+ * `--name: inherit;` would NOT do this: at :root there is no parent, so
79
+ * an unregistered custom property's `inherit` resolves to its own
80
+ * initial value -- the guaranteed-invalid value -- exactly as if it were
81
+ * never declared. An EMPTY value is what actually works: var(--name,
82
+ * <fallback>) uses <fallback> only while --name is unset; once --name
83
+ * has ANY value, even an empty one, that value is substituted instead,
84
+ * which here leaves the declaration with no value at all -- invalid at
85
+ * computed-value time, which for an inherited property computes to
86
+ * exactly the old behaviour: inherit from the ancestor.
87
+ */
88
+ :root { --loader-sub-text-color: ; } /* color on .sub-text (src/lib/BrandLoader/BrandLoader.svelte:87) was inherited, never declared */
89
+ :root { --phone-screen-color: ; } /* color on .phone-screen (src/lib/Phone/Phone.svelte:104) was inherited, never declared */
90
+
91
+
92
+ /*
93
+ * Not pinned above -- each of these already had more than one literal
94
+ * fallback across src/lib before this change, so no single :root rule
95
+ * could restore "the previous default" without being wrong at some call
96
+ * site. Review the sites below by hand if your snapshots depend on them.
97
+ */
98
+ /* --chart-empty-color: light-dark(#9ca3af, #6b7280) (src/lib/AreaChart/AreaChart.svelte:600), #9ca3af (src/lib/PieChart/PieChart.svelte:505) */
99
+ /* --status-description-font-color: #2f3841 (src/lib/Status/Status.svelte:95), #436484cc (src/lib/Status/Status.svelte:100) */
100
+ /* --step-text-failure-color: #e53935 (src/lib/Stepper/Step.svelte:159), #ef5350 (src/lib/Stepper/Stepper.svelte:182) */
101
+ /* --step-text-in-progress-color: #f59e0b (src/lib/Stepper/Step.svelte:168), #fbbf24 (src/lib/Stepper/Stepper.svelte:194) */
102
+ /* --stepper-separator-background-image-failure-color: #e53935 (src/lib/Stepper/Stepper.svelte:127), #ef5350 (src/lib/Stepper/Stepper.svelte:183) */
103
+ /* --stepper-separator-background-image-in-progress-color: #f59e0b (src/lib/Stepper/Stepper.svelte:141), #fbbf24 (src/lib/Stepper/Stepper.svelte:195) */
104
+ /* --stepper-status-failure-color: #e53935 (src/lib/Stepper/Step.svelte:162), #ef5350 (src/lib/Stepper/Stepper.svelte:189) */
105
+ /* --stepper-status-in-progress-color: #f59e0b (src/lib/Stepper/Step.svelte:171), #fbbf24 (src/lib/Stepper/Stepper.svelte:201) */
106
+ /* --tabs-item-color: #666666 (src/lib/Tabs/Tabs.svelte:407), #999999 (src/lib/Tabs/Tabs.svelte:611) */