@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,301 @@
1
+ import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
2
+ import { join, relative, resolve } from 'node:path';
3
+ import { parseArgs } from 'node:util';
4
+ import { pathToFileURL } from 'node:url';
5
+ /**
6
+ * 3.x's ChartTooltip unification: PieChart and SankeyChart's own custom-tooltip
7
+ * wrapper, `<div class="chart-tooltip-slot">`, was replaced by the shared
8
+ * `<ChartTooltip>` -- see `src/lib/_chart/ChartTooltip.svelte`. That component
9
+ * renders EVERY tooltip, default and custom alike, with the base class
10
+ * `chart-tooltip`; `unstyled` is added only for the custom-snippet case (the
11
+ * one `.chart-tooltip-slot` ever meant), and `portal` only when `tooltipPortal`
12
+ * is set (independent of `unstyled` -- both branches carry it). A consumer
13
+ * stylesheet selecting `.chart-tooltip-slot` now matches nothing, with no
14
+ * error: a CSS selector matching zero elements is not a build or runtime
15
+ * failure, so this is the one 3.x break a type checker or test suite cannot
16
+ * catch on a consumer's behalf.
17
+ *
18
+ * The correct rewrite is therefore `.chart-tooltip-slot` -> `.chart-tooltip.unstyled`,
19
+ * never bare `.chart-tooltip`: the base class alone also matches every
20
+ * DEFAULT tooltip in every chart, so a rewrite that dropped `.unstyled` would
21
+ * fix the break for the consumer's own custom tooltip while silently leaking
22
+ * their styling onto every chart's default one -- a new break introduced while
23
+ * fixing the old one. `.unstyled` is appended after whatever token the source
24
+ * selector already ends with rather than inserted before it, so a selector
25
+ * that was already qualified (`.chart-tooltip-slot.portal`) keeps that
26
+ * qualifier exactly once, in place, rather than gaining a duplicate or a
27
+ * reordered compound -- compound class selectors match regardless of token
28
+ * order, so `.chart-tooltip.unstyled.portal` matches precisely the portalled
29
+ * custom-snippet element, same as `.chart-tooltip.portal.unstyled` would.
30
+ *
31
+ * This is mechanical for the class token itself, but nothing here parses
32
+ * selector grammar, so it rewrites `.chart-tooltip-slot` wherever it is
33
+ * genuinely a class-selector token: in a consumer's `.css` files, inside the
34
+ * `<style>` block of its `.svelte` files, and inside the string argument of a
35
+ * `querySelector`/`querySelectorAll`/`closest`/`matches` call in a `.svelte`
36
+ * file's `<script>` block (see the doc comment on SELECTOR_CALL for why that
37
+ * last one and nothing broader in script code). A `.svelte` file's own
38
+ * template is left untouched -- see rewriteSvelteFile.
39
+ *
40
+ * node --experimental-strip-types scripts/migrate/chart-tooltip-selector.ts [--apply] <consumer-root>
41
+ *
42
+ * Reports by default; nothing is written without --apply, matching every other
43
+ * script in this directory.
44
+ */
45
+ const USAGE = [
46
+ 'Usage: node scripts/migrate/chart-tooltip-selector.ts [--apply] <consumer-root>',
47
+ '',
48
+ 'Rewrites the .chart-tooltip-slot selector PieChart and SankeyChart rendered',
49
+ 'before 3.x to .chart-tooltip.unstyled -- the shared <ChartTooltip> renders',
50
+ 'every tooltip with the bare .chart-tooltip class, so .unstyled is what keeps',
51
+ 'the match limited to the custom-snippet tooltip, as before -- across a',
52
+ "consumer project's .css and .svelte files. Reports by default; --apply",
53
+ 'writes the rewritten files.',
54
+ '',
55
+ ' --apply write the rewritten files',
56
+ ' --help show this help'
57
+ ].join('\n');
58
+ const SKIP = new Set([
59
+ 'node_modules',
60
+ '.git',
61
+ '.svelte-kit',
62
+ 'dist',
63
+ 'dist-wc',
64
+ 'build',
65
+ 'coverage',
66
+ 'playwright-report',
67
+ 'test-results'
68
+ ]);
69
+ /** A class-selector token, never a substring of a longer class name on either side. */
70
+ const CLASS_SELECTOR = /\.chart-tooltip-slot(?![\w-])/g;
71
+ /**
72
+ * Rewrites every bare `.chart-tooltip-slot` class-selector token to
73
+ * `.chart-tooltip.unstyled`, in place inside whatever surrounding selector it
74
+ * sits in.
75
+ *
76
+ * Not bare `.chart-tooltip`: `ChartTooltip.svelte` gives EVERY tooltip that
77
+ * base class, default charts included, and adds `unstyled` only for the
78
+ * custom-snippet wrapper `.chart-tooltip-slot` used to name exclusively. A
79
+ * rewrite that dropped `.unstyled` would still fix the consumer's own broken
80
+ * selector, but it would also start matching every default tooltip in every
81
+ * chart on the page -- trading the one break this migration is closing for a
82
+ * new one it would introduce. Appending `.unstyled` immediately after the
83
+ * replaced token, rather than inserting it before whatever already follows,
84
+ * is what keeps a selector that was already qualified
85
+ * (`.chart-tooltip-slot.portal`) from gaining a duplicate or reordered
86
+ * qualifier -- it becomes `.chart-tooltip.unstyled.portal`, and a compound
87
+ * class selector matches on the set of tokens present, not their order, so
88
+ * that is exactly equivalent to `.chart-tooltip.portal.unstyled`.
89
+ *
90
+ * Requiring a literal `.` immediately before the token is what keeps
91
+ * `.my-chart-tooltip-slot` alone: there is no `.` directly before "chart"
92
+ * there, only a `-`, so the pattern never starts matching inside it. The
93
+ * trailing `(?![\w-])` is the other half -- it stops `.chart-tooltip-slot-header`
94
+ * or the unrelated `.chart-tooltip-slots` from matching on their shared prefix.
95
+ * Because only the matched substring is replaced -- the rest of the selector is
96
+ * untouched text on either side -- a compound selector
97
+ * (`.foo .chart-tooltip-slot > .bar`, `.chart-tooltip-slot.portal`) keeps its
98
+ * combinators and structure exactly; nothing here parses selector grammar.
99
+ */
100
+ export function rewriteCss(source) {
101
+ let count = 0;
102
+ const code = source.replace(CLASS_SELECTOR, () => {
103
+ count += 1;
104
+ return '.chart-tooltip.unstyled';
105
+ });
106
+ return { code, count };
107
+ }
108
+ /**
109
+ * The string-literal argument of a querySelector/querySelectorAll/closest/
110
+ * matches call. Deliberately narrow: rewriting `.chart-tooltip-slot` wherever
111
+ * the substring appears in script code would also catch a code comment, a test
112
+ * fixture string, or a log message quoting the old class name for reference,
113
+ * and silently rewriting those changes what they *say* rather than what they
114
+ * *do*. Restricting to the argument of a selector-reading DOM method gives the
115
+ * same guarantee the CSS case gets for free from sitting inside a `<style>`
116
+ * block: the matched text is actually being used as a CSS selector, not merely
117
+ * mentioning one. `rewriteScript`'s own test proves the narrower half of that
118
+ * trade: a bare mention outside such a call is left alone.
119
+ */
120
+ const SELECTOR_CALL = /(\b(?:querySelector|querySelectorAll|closest|matches)\s*\(\s*)(['"`])((?:\\.|(?!\2)[\s\S])*)(\2\s*\))/g;
121
+ export function rewriteScript(source) {
122
+ let count = 0;
123
+ const code = source.replace(SELECTOR_CALL, (_full, prefix, quote, body, suffix) => {
124
+ const rewritten = rewriteCss(body);
125
+ count += rewritten.count;
126
+ return `${prefix}${quote}${rewritten.code}${suffix}`;
127
+ });
128
+ return { code, count };
129
+ }
130
+ /**
131
+ * Splices `rewrite`'s output back into `source` at each match of `blockPattern`,
132
+ * leaving everything outside the captured group untouched. `contentStart`
133
+ * bridges the match offset (which points at the opening tag) to where the
134
+ * captured content actually begins -- the same bridge `analyze.ts` uses for its
135
+ * `legacy-back-selector` line numbers, needed here for the same reason: the
136
+ * tag's own length would otherwise misplace where the replacement is spliced in
137
+ * for any block that isn't on the file's first line.
138
+ */
139
+ function rewriteBlocks(source, blockPattern, rewrite) {
140
+ let count = 0;
141
+ let out = '';
142
+ let last = 0;
143
+ for (const match of source.matchAll(blockPattern)) {
144
+ const whole = match[0];
145
+ const content = match[1];
146
+ const start = match.index ?? 0;
147
+ const contentStart = start + whole.indexOf(content);
148
+ out += source.slice(last, contentStart);
149
+ const rewritten = rewrite(content);
150
+ out += rewritten.code;
151
+ count += rewritten.count;
152
+ last = contentStart + content.length;
153
+ }
154
+ out += source.slice(last);
155
+ return { code: out, count };
156
+ }
157
+ const STYLE_BLOCK = /<style[^>]*>([\s\S]*?)<\/style>/g;
158
+ const SCRIPT_BLOCK = /<script[^>]*>([\s\S]*?)<\/script>/g;
159
+ /**
160
+ * Rewrites a `.svelte` file's `<style>` and `<script>` blocks only. The
161
+ * template is left alone on purpose: `chart-tooltip-slot` was PieChart/
162
+ * SankeyChart's own internal wrapper, never a prop, slot, or class name a
163
+ * consumer's own markup had reason to write -- so the only places the old name
164
+ * can legitimately appear in a `.svelte` file are a global style rule reaching
165
+ * for it and a script reading the DOM for it. A literal `class="chart-tooltip-
166
+ * slot"` sitting in a consumer's own template is that consumer's own class,
167
+ * coincidentally named, and rewriting it would change markup this rename never
168
+ * touched.
169
+ */
170
+ export function rewriteSvelteFile(source) {
171
+ const afterStyle = rewriteBlocks(source, STYLE_BLOCK, rewriteCss);
172
+ const afterScript = rewriteBlocks(afterStyle.code, SCRIPT_BLOCK, rewriteScript);
173
+ return {
174
+ code: afterScript.code,
175
+ selectorCount: afterStyle.count,
176
+ scriptCount: afterScript.count
177
+ };
178
+ }
179
+ function targetFiles(root) {
180
+ const found = [];
181
+ const visit = (dir) => {
182
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
183
+ if (entry.isDirectory()) {
184
+ if (!SKIP.has(entry.name)) {
185
+ visit(join(dir, entry.name));
186
+ }
187
+ continue;
188
+ }
189
+ if (entry.name.endsWith('.css') || entry.name.endsWith('.svelte')) {
190
+ found.push(join(dir, entry.name));
191
+ }
192
+ }
193
+ };
194
+ visit(root);
195
+ return found;
196
+ }
197
+ /** Every `.css`/`.svelte` file under `root` this rename would change, with its rewritten text. */
198
+ export function planSelectorRewrites(root) {
199
+ const plans = [];
200
+ for (const file of targetFiles(root)) {
201
+ const source = readFileSync(file, 'utf8');
202
+ if (file.endsWith('.css')) {
203
+ const result = rewriteCss(source);
204
+ if (result.count > 0) {
205
+ plans.push({ file, code: result.code, selectorCount: result.count, scriptCount: 0 });
206
+ }
207
+ continue;
208
+ }
209
+ const result = rewriteSvelteFile(source);
210
+ if (result.selectorCount > 0 || result.scriptCount > 0) {
211
+ plans.push({
212
+ file,
213
+ code: result.code,
214
+ selectorCount: result.selectorCount,
215
+ scriptCount: result.scriptCount
216
+ });
217
+ }
218
+ }
219
+ return plans;
220
+ }
221
+ /**
222
+ * Checked directly against `src/lib/_chart/ChartTooltip.svelte`: both the
223
+ * portalled and inline branches of its template carry `data-pw="chart-tooltip"`
224
+ * unconditionally, so it is present whether or not `unstyled`/`portal` are set
225
+ * -- unlike a class list, which is exactly what this migration exists because a
226
+ * consumer relied on.
227
+ */
228
+ const RECOMMENDATION = [
229
+ '',
230
+ 'More durable than either selector: ChartTooltip always sets',
231
+ '`data-pw="chart-tooltip"` (present on both the portalled and inline branch,',
232
+ 'independent of `unstyled`/`portal` -- verified against',
233
+ 'src/lib/_chart/ChartTooltip.svelte), so `[data-pw="chart-tooltip"]` survives',
234
+ "the next class rename the way `.chart-tooltip-slot` just didn't."
235
+ ].join('\n');
236
+ export function run(argv, log) {
237
+ let parsed;
238
+ try {
239
+ parsed = parseArgs({
240
+ args: [...argv],
241
+ options: {
242
+ apply: { type: 'boolean', default: false },
243
+ help: { type: 'boolean', default: false }
244
+ },
245
+ allowPositionals: true
246
+ });
247
+ }
248
+ catch (error) {
249
+ log(error instanceof Error ? error.message : String(error));
250
+ log(USAGE);
251
+ return { exitCode: 2, filesScanned: 0, rewrites: [], applied: false };
252
+ }
253
+ if (parsed.values.help === true || parsed.positionals.length !== 1) {
254
+ log(USAGE);
255
+ return {
256
+ exitCode: parsed.values.help === true ? 0 : 2,
257
+ filesScanned: 0,
258
+ rewrites: [],
259
+ applied: false
260
+ };
261
+ }
262
+ const root = resolve(parsed.positionals[0]);
263
+ if (!existsSync(root) || !statSync(root).isDirectory()) {
264
+ log(`error: ${root} is not a directory`);
265
+ return { exitCode: 2, filesScanned: 0, rewrites: [], applied: false };
266
+ }
267
+ const apply = parsed.values.apply === true;
268
+ const files = targetFiles(root);
269
+ const rewrites = planSelectorRewrites(root);
270
+ for (const rewrite of rewrites) {
271
+ const parts = [
272
+ rewrite.selectorCount > 0 ? `${rewrite.selectorCount} selector(s)` : '',
273
+ rewrite.scriptCount > 0 ? `${rewrite.scriptCount} querySelector string(s)` : ''
274
+ ].filter((part) => part.length > 0);
275
+ log(`${relative(root, rewrite.file)}: ${parts.join(', ')}`);
276
+ if (apply) {
277
+ writeFileSync(rewrite.file, rewrite.code);
278
+ }
279
+ }
280
+ if (rewrites.length === 0) {
281
+ log(`No .chart-tooltip-slot selector found across ${files.length} .css/.svelte file(s).`);
282
+ }
283
+ else {
284
+ log(RECOMMENDATION);
285
+ }
286
+ const totalSelectors = rewrites.reduce((sum, rewrite) => sum + rewrite.selectorCount, 0);
287
+ const totalScript = rewrites.reduce((sum, rewrite) => sum + rewrite.scriptCount, 0);
288
+ log('');
289
+ log(`${apply ? 'rewrote' : 'would rewrite'} ${totalSelectors} selector(s) and ${totalScript} querySelector string(s) across ${rewrites.length} of ${files.length} file(s)`);
290
+ return { exitCode: 0, filesScanned: files.length, rewrites, applied: apply };
291
+ }
292
+ // Comparing against a basename split on '/' fails on Windows, where argv[1] uses
293
+ // backslashes and the split yields the whole path -- the CLI then silently
294
+ // declines to run. Normalising both sides to a file URL is platform-agnostic;
295
+ // mirrors cli.ts's own guard.
296
+ const entrypoint = process.argv[1];
297
+ const invokedDirectly = typeof entrypoint === 'string' && import.meta.url === pathToFileURL(resolve(entrypoint)).href;
298
+ if (invokedDirectly) {
299
+ const summary = run(process.argv.slice(2), (line) => console.log(line));
300
+ process.exitCode = summary.exitCode;
301
+ }