jsswift 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,437 @@
1
+ UI.Table = (...args) => {
2
+ const { props, children } = JSswift.uiNormalizeArgs(args);
3
+ const slots = props.slots || {};
4
+ const columns = Array.isArray(props.columns) ? props.columns : [];
5
+ const basePageSizes = tableNormalizePageSizes(props.pageSizeOptions, [5, 10, 20, 50]);
6
+ const initialPageSize = Number(props.pageSize ?? basePageSizes[0] ?? 10) || 10;
7
+ const pageSizes = Array.from(new Set([...basePageSizes, initialPageSize])).sort((a, b) => a - b);
8
+ const initialSort = props.initialSort || (props.sortBy ? { key: props.sortBy, dir: props.sortDir === "desc" ? "desc" : "asc" } : null);
9
+ const searchable = props.searchable === true
10
+ || typeof props.searchable === "string"
11
+ || props.searchPlaceholder != null
12
+ || props.search != null
13
+ || props.query != null
14
+ || !!props.searchModel
15
+ || !!props.queryModel
16
+ || Array.isArray(props.searchKeys)
17
+ || typeof props.searchBy === "function"
18
+ || typeof props.searchPredicate === "function";
19
+ const searchModel = resolveModel(props.searchModel || props.queryModel, "UI.Table:query");
20
+
21
+ const [getPage, setPage] = app.reactive.signal(Math.max(1, Number(props.page || 1) || 1));
22
+ const [getPageSize, setPageSizeState] = app.reactive.signal(initialPageSize);
23
+ const [getSort, setSort] = app.reactive.signal(initialSort);
24
+ const [getQuery, setQueryState] = app.reactive.signal(String((searchModel ? searchModel.get() : (props.search ?? props.query)) ?? ""));
25
+
26
+ const setQuery = (value) => {
27
+ const next = String(value ?? "");
28
+ setQueryState(next);
29
+ if (searchModel) searchModel.set(next);
30
+ setPage(1);
31
+ };
32
+ const setPageSize = (value) => {
33
+ const next = Number(value) || initialPageSize;
34
+ setPageSizeState(next);
35
+ setPage(1);
36
+ };
37
+ const toggleSort = (col, index) => {
38
+ const nextKey = tableColumnSortKey(col, index);
39
+ const current = getSort();
40
+ if (!current || (current.key !== nextKey && current.key !== col?.key)) setSort({ key: nextKey, dir: "asc" });
41
+ else if (current.dir === "asc") setSort({ key: nextKey, dir: "desc" });
42
+ else setSort(null);
43
+ setPage(1);
44
+ };
45
+
46
+ let searchInput = null;
47
+ let stopSearchWatch;
48
+ if (searchModel) {
49
+ stopSearchWatch = searchModel.watch((value) => {
50
+ const next = String(value ?? "");
51
+ setQueryState(next);
52
+ if (searchInput && searchInput.value !== next) searchInput.value = next;
53
+ setPage(1);
54
+ }, "UI.Table:queryWatch");
55
+ }
56
+
57
+ const wrapProps = JSswift.omit(props, [
58
+ "columns", "rows", "rowKey", "loading", "page", "pageSize", "pageSizeOptions", "pagination",
59
+ "initialSort", "sortBy", "sortDir", "search", "query", "searchable", "searchPlaceholder",
60
+ "searchKeys", "searchBy", "searchPredicate", "searchModel", "queryModel", "filter",
61
+ "actions", "actionsLabel", "emptyText", "loadingText", "onRowClick", "onRowDblClick",
62
+ "tableClass", "tableStyle", "cardClass", "dense", "striped", "hover", "stickyHeader",
63
+ "toolbar", "toolbarStart", "toolbarEnd", "caption", "footer", "status", "rowClass", "rowAttrs",
64
+ "minTableWidth", "hideHeader", "hideFooter", "hideStatus", "slots", "body"
65
+ ]);
66
+ wrapProps.class = uiClass(["jss-table-card", props.class, props.cardClass]);
67
+ if (props.dense != null) wrapProps.dense = props.dense;
68
+
69
+ const shell = _.div({ class: "jss-table-shell" });
70
+ const leadNodes = renderSlotToArray(slots, "default", {}, children);
71
+ if (leadNodes.length) shell.appendChild(_.div({ class: "jss-table-lead" }, ...leadNodes));
72
+
73
+ const toolbarStartNodes = renderSlotToArray(slots, "toolbarStart", {}, props.toolbarStart);
74
+ const toolbarNodes = renderSlotToArray(slots, "toolbar", {}, props.toolbar);
75
+ const toolbarEndNodes = renderSlotToArray(slots, "toolbarEnd", {}, props.toolbarEnd);
76
+
77
+ const toolbar = _.div({ class: "jss-table-toolbar" });
78
+ const toolbarMain = _.div({ class: "jss-table-toolbar-main" });
79
+ const toolbarSide = _.div({ class: "jss-table-toolbar-side" });
80
+ toolbarStartNodes.forEach((node) => toolbarMain.appendChild(node));
81
+ toolbarNodes.forEach((node) => toolbarMain.appendChild(node));
82
+
83
+ const searchSlotNodes = renderSlotToArray(slots, "search", { query: getQuery(), getQuery, setQuery }, null);
84
+ if (searchSlotNodes.length) {
85
+ searchSlotNodes.forEach((node) => toolbarSide.appendChild(node));
86
+ } else if (searchable) {
87
+ searchInput = _.input({
88
+ type: "search",
89
+ class: "jss-input",
90
+ placeholder: typeof props.searchable === "string" ? props.searchable : (props.searchPlaceholder || "Cerca nella tabella"),
91
+ value: String(getQuery() || "")
92
+ });
93
+ searchInput.addEventListener("input", () => setQuery(searchInput.value));
94
+ const clearSearch = UI.Btn({
95
+ class: "jss-table-search-clear",
96
+ outline: true,
97
+ onClick: () => {
98
+ if (searchInput) searchInput.value = "";
99
+ setQuery("");
100
+ }
101
+ }, "Reset");
102
+ toolbarSide.appendChild(
103
+ _.div({ class: "jss-singularity jss-table-search" },
104
+ _.span({ class: "jss-table-search-icon", "aria-hidden": "true" }, "⌕"),
105
+ searchInput,
106
+ clearSearch
107
+ )
108
+ );
109
+ }
110
+ toolbarEndNodes.forEach((node) => toolbarSide.appendChild(node));
111
+ if (toolbarMain.childNodes.length || toolbarSide.childNodes.length) {
112
+ toolbar.appendChild(toolbarMain);
113
+ toolbar.appendChild(toolbarSide);
114
+ shell.appendChild(toolbar);
115
+ }
116
+
117
+ const statusSummary = _.div({ class: "jss-singularity jss-table-chip" }, "");
118
+ const statusFilter = _.div({ class: "jss-singularity jss-table-chip" }, "");
119
+ const statusSort = _.div({ class: "jss-singularity jss-table-chip" }, "");
120
+ const statusExtraNodes = renderSlotToArray(slots, "status", {}, props.status);
121
+ const status = _.div({ class: "jss-table-status" },
122
+ statusSummary,
123
+ statusFilter,
124
+ statusSort,
125
+ ...statusExtraNodes
126
+ );
127
+ if (props.hideStatus !== true) shell.appendChild(status);
128
+
129
+ const captionNodes = renderSlotToArray(slots, "caption", {}, props.caption);
130
+ if (captionNodes.length) shell.appendChild(_.div({ class: "jss-table-caption" }, ...captionNodes));
131
+
132
+ const thead = _.thead();
133
+ const tbody = _.tbody();
134
+ const hasActions = !!props.actions || !!slots.actions;
135
+
136
+ const tableClass = uiClass([
137
+ "jss-table",
138
+ uiWhen(props.dense, "dense"),
139
+ uiWhen(props.striped, "striped"),
140
+ uiWhen(props.hover !== false, "hover"),
141
+ uiWhen(props.stickyHeader !== false, "sticky-head"),
142
+ props.tableClass
143
+ ]);
144
+ const tableStyle = {
145
+ ...(props.tableStyle || {})
146
+ };
147
+ if (props.minTableWidth != null) tableStyle["--jss-table-min-width"] = toCssSize(props.minTableWidth);
148
+ const table = _.table({ class: tableClass, style: tableStyle }, thead, tbody);
149
+ const wrapTable = _.div({ class: "jss-singularity jss-table-wrap" }, table);
150
+ shell.appendChild(wrapTable);
151
+
152
+ const pagerInfo = _.div({ class: "jss-singularity jss-table-chip" }, "");
153
+ const pagerMeta = _.div({ class: "jss-singularity jss-table-chip" }, "");
154
+ const btnPrev = UI.Btn({ outline: true, onClick: () => setPage(Math.max(1, getPage() - 1)) }, "‹");
155
+ const btnNext = UI.Btn({ outline: true, onClick: () => setPage(getPage() + 1) }, "›");
156
+ const pageChip = _.div({ class: "jss-singularity jss-table-chip" }, "");
157
+ const sizeSelect = _.select({ class: "jss-input jss-table-size-select" },
158
+ ...pageSizes.map((size) => uiOptionNode({ value: String(size) }, String(size)))
159
+ );
160
+ sizeSelect.value = String(getPageSize());
161
+ sizeSelect.addEventListener("change", () => setPageSize(sizeSelect.value));
162
+ const footerExtraNodes = renderSlotToArray(slots, "footer", {}, props.footer);
163
+
164
+ const footer = _.div({ class: "jss-table-foot" },
165
+ _.div({ class: "jss-table-foot-main" },
166
+ pagerInfo,
167
+ pagerMeta,
168
+ _.label({ class: "jss-table-size" },
169
+ _.span("Righe"),
170
+ sizeSelect
171
+ )
172
+ ),
173
+ _.div({ class: "jss-table-foot-extra" },
174
+ ...footerExtraNodes,
175
+ _.div({ class: "jss-table-pager" },
176
+ btnPrev,
177
+ pageChip,
178
+ btnNext
179
+ )
180
+ )
181
+ );
182
+ if (props.hideFooter !== true) shell.appendChild(footer);
183
+
184
+ const renderHeader = () => {
185
+ thead.innerHTML = "";
186
+ if (props.hideHeader) return;
187
+
188
+ const row = _.tr();
189
+ columns.forEach((col, colIndex) => {
190
+ const ctx = { col, colIndex, sort: getSort() };
191
+ const thStyle = {
192
+ ...tableResolveStyle(col?.style, { ...ctx, header: true }),
193
+ ...tableResolveStyle(col?.headerStyle ?? col?.thStyle, { ...ctx, header: true })
194
+ };
195
+ if (col?.width != null) thStyle.width = toCssSize(col.width);
196
+ if (col?.minWidth != null) thStyle.minWidth = toCssSize(col.minWidth);
197
+ if (col?.maxWidth != null) thStyle.maxWidth = toCssSize(col.maxWidth);
198
+ if (col?.align) thStyle.textAlign = col.align;
199
+ let headerNodes = renderSlotToArray(col?.slots, "header", ctx, null);
200
+ if (!headerNodes.length) {
201
+ const fallback = typeof col?.header === "function" ? col.header(ctx) : (col?.header ?? tableColumnLabel(col));
202
+ headerNodes = renderSlotToArray(slots, "header", ctx, fallback);
203
+ }
204
+
205
+ const currentSort = getSort();
206
+ const sortKey = tableColumnSortKey(col, colIndex);
207
+ const isSortable = col?.sortable !== false && (col?.key != null || typeof col?.get === "function" || typeof col?.compare === "function");
208
+ const isActive = !!currentSort && (currentSort.key === sortKey || currentSort.key === col?.key);
209
+ const th = _.th({
210
+ class: uiClass([
211
+ "jss-table-head-cell",
212
+ uiWhen(col?.nowrap, "is-nowrap"),
213
+ uiWhen(isSortable, "jss-table-sortable"),
214
+ uiWhen(isActive, "is-sorted"),
215
+ col?.headerClass
216
+ ]),
217
+ style: thStyle
218
+ });
219
+
220
+ if (isSortable) {
221
+ th.appendChild(
222
+ _.button({
223
+ type: "button",
224
+ class: "jss-table-head-button",
225
+ onClick: () => toggleSort(col, colIndex)
226
+ },
227
+ _.span({ class: "jss-table-head-label" }, ...headerNodes),
228
+ _.span({ class: "jss-table-head-arrow", "aria-hidden": "true" },
229
+ isActive ? (currentSort.dir === "asc" ? "↑" : "↓") : "↕"
230
+ )
231
+ )
232
+ );
233
+ } else {
234
+ headerNodes.forEach((node) => th.appendChild(node));
235
+ }
236
+ row.appendChild(th);
237
+ });
238
+
239
+ if (hasActions) {
240
+ const actionsHeaderNodes = renderSlotToArray(slots, "actionsHeader", {}, props.actionsLabel || "Azioni");
241
+ row.appendChild(
242
+ _.th({ class: "jss-table-head-cell jss-table-head-actions", style: { textAlign: "right" } }, ...actionsHeaderNodes)
243
+ );
244
+ }
245
+ thead.appendChild(row);
246
+ };
247
+
248
+ const renderStateRow = (slotName, fallback) => {
249
+ const ctx = { columns, count: columns.length };
250
+ const nodes = renderSlotToArray(slots, slotName, ctx, fallback);
251
+ const colSpan = String(columns.length + (hasActions ? 1 : 0));
252
+ tbody.appendChild(
253
+ _.tr(
254
+ _.td({ colSpan, class: "jss-table-state" }, ...nodes)
255
+ )
256
+ );
257
+ };
258
+
259
+ const stopRender = app.reactive.effect(() => {
260
+ const rows = tableToArray(props.rows);
261
+ const query = String(getQuery() || "").trim();
262
+ const currentSort = getSort();
263
+ const loading = typeof props.loading === "function" ? !!props.loading() : !!props.loading;
264
+ const paginationEnabled = props.pagination !== false;
265
+
266
+ renderHeader();
267
+ tbody.innerHTML = "";
268
+ if (searchInput && searchInput.value !== getQuery()) searchInput.value = getQuery();
269
+ if (sizeSelect.value !== String(getPageSize())) sizeSelect.value = String(getPageSize());
270
+
271
+ if (loading) {
272
+ statusSummary.textContent = "Caricamento in corso";
273
+ statusFilter.style.display = "none";
274
+ statusSort.style.display = "none";
275
+ pagerInfo.textContent = "Loading…";
276
+ pagerMeta.textContent = "";
277
+ pageChip.textContent = "Pagina 1";
278
+ btnPrev.disabled = true;
279
+ btnNext.disabled = true;
280
+ renderStateRow("loading", props.loadingText || "Loading...");
281
+ return;
282
+ }
283
+
284
+ let list = rows.slice();
285
+ const datasetTotal = list.length;
286
+ if (typeof props.filter === "function") {
287
+ list = list.filter((row, index) => props.filter(row, { row, index, query, rows, columns }));
288
+ }
289
+ if (query) {
290
+ list = list.filter((row) => tableMatchesQuery(row, columns, query, props));
291
+ }
292
+
293
+ if (currentSort) {
294
+ const sortCol = tableFindColumn(columns, currentSort.key);
295
+ if (sortCol) {
296
+ list.sort((a, b) => {
297
+ const av = tableResolveValue(sortCol, a, -1);
298
+ const bv = tableResolveValue(sortCol, b, -1);
299
+ const out = typeof sortCol.compare === "function"
300
+ ? sortCol.compare(av, bv, a, b)
301
+ : defaultCompare(av, bv);
302
+ return currentSort.dir === "asc" ? out : -out;
303
+ });
304
+ }
305
+ }
306
+
307
+ const filteredTotal = list.length;
308
+ const currentPageSize = Math.max(1, Number(getPageSize()) || initialPageSize);
309
+ const pages = paginationEnabled ? Math.max(1, Math.ceil(filteredTotal / currentPageSize)) : 1;
310
+ const page = paginationEnabled ? Math.min(getPage(), pages) : 1;
311
+ if (page !== getPage()) setPage(page);
312
+
313
+ const start = paginationEnabled ? (page - 1) * currentPageSize : 0;
314
+ const end = paginationEnabled ? start + currentPageSize : filteredTotal;
315
+ const pageRows = list.slice(start, end);
316
+
317
+ statusSummary.textContent = filteredTotal === datasetTotal
318
+ ? `${filteredTotal} righe`
319
+ : `${filteredTotal} di ${datasetTotal} righe`;
320
+ statusFilter.textContent = query ? `Ricerca: ${query}` : "";
321
+ statusFilter.style.display = query ? "" : "none";
322
+ if (currentSort) {
323
+ const sortCol = tableFindColumn(columns, currentSort.key);
324
+ statusSort.textContent = sortCol
325
+ ? `Ordine: ${tableColumnLabel(sortCol)} ${currentSort.dir === "asc" ? "↑" : "↓"}`
326
+ : "";
327
+ statusSort.style.display = sortCol ? "" : "none";
328
+ } else {
329
+ statusSort.style.display = "none";
330
+ }
331
+
332
+ pagerInfo.textContent = filteredTotal
333
+ ? `${start + 1}-${Math.min(end, filteredTotal)} di ${filteredTotal}`
334
+ : "0 risultati";
335
+ pagerMeta.textContent = filteredTotal !== datasetTotal ? `Dataset totale ${datasetTotal}` : `Page size ${currentPageSize}`;
336
+ pageChip.textContent = paginationEnabled ? `Pagina ${page} / ${pages}` : "Tutte le righe";
337
+ btnPrev.disabled = !paginationEnabled || page <= 1;
338
+ btnNext.disabled = !paginationEnabled || page >= pages;
339
+ sizeSelect.disabled = !paginationEnabled;
340
+ sizeSelect.parentNode.style.display = paginationEnabled ? "" : "none";
341
+
342
+ if (pageRows.length === 0) {
343
+ renderStateRow("empty", props.emptyText || "Nessun dato");
344
+ return;
345
+ }
346
+
347
+ for (let pageIndex = 0; pageIndex < pageRows.length; pageIndex++) {
348
+ const row = pageRows[pageIndex];
349
+ const rowIndex = start + pageIndex;
350
+ const rowCtx = { row, rowIndex, pageIndex };
351
+ const rowAttrs = typeof props.rowAttrs === "function" ? (props.rowAttrs(row, rowCtx) || {}) : (props.rowAttrs || {});
352
+ const rowClass = typeof props.rowClass === "function" ? props.rowClass(row, rowCtx) : props.rowClass;
353
+ const isInteractiveRow = !!(props.onRowClick || props.onRowDblClick);
354
+ const tr = _.tr({
355
+ ...rowAttrs,
356
+ class: uiClass([
357
+ "jss-table-row",
358
+ rowClass,
359
+ rowAttrs.class,
360
+ uiWhen(isInteractiveRow, "is-clickable")
361
+ ])
362
+ });
363
+
364
+ if (props.rowKey) {
365
+ const key = typeof props.rowKey === "function" ? props.rowKey(row, rowCtx) : tableGetByPath(row, props.rowKey);
366
+ if (key != null) tr.dataset.key = String(key);
367
+ }
368
+
369
+ const shouldIgnoreRowEvent = (event) => {
370
+ const target = event?.target;
371
+ return !!(target && target.closest && target.closest("button, a, input, select, textarea, label, [data-table-action]"));
372
+ };
373
+ if (props.onRowClick) {
374
+ tr.addEventListener("click", (event) => {
375
+ if (shouldIgnoreRowEvent(event)) return;
376
+ props.onRowClick(row, rowCtx, event);
377
+ });
378
+ }
379
+ if (props.onRowDblClick) {
380
+ tr.addEventListener("dblclick", (event) => {
381
+ if (shouldIgnoreRowEvent(event)) return;
382
+ props.onRowDblClick(row, rowCtx, event);
383
+ });
384
+ }
385
+
386
+ columns.forEach((col, colIndex) => {
387
+ const value = tableResolveValue(col, row, rowIndex);
388
+ const cellCtx = { ...rowCtx, col, colIndex, value };
389
+ const tdStyle = {
390
+ ...tableResolveStyle(col?.style, cellCtx),
391
+ ...tableResolveStyle(col?.cellStyle ?? col?.tdStyle, cellCtx)
392
+ };
393
+ if (col?.align) tdStyle.textAlign = col.align;
394
+ if (col?.width != null) tdStyle.width = toCssSize(col.width);
395
+ if (col?.minWidth != null) tdStyle.minWidth = toCssSize(col.minWidth);
396
+ if (col?.maxWidth != null) tdStyle.maxWidth = toCssSize(col.maxWidth);
397
+ const cellClass = typeof col?.cellClass === "function" ? col.cellClass(row, cellCtx) : (col?.cellClass || col?.class);
398
+ const td = _.td({
399
+ class: uiClass(["jss-table-cell", cellClass, uiWhen(col?.nowrap, "is-nowrap")]),
400
+ style: tdStyle
401
+ });
402
+
403
+ let cellNodes = renderSlotToArray(col?.slots, "cell", cellCtx, null);
404
+ if (!cellNodes.length) {
405
+ const raw = typeof col?.render === "function"
406
+ ? col.render(row, cellCtx)
407
+ : (typeof col?.format === "function" ? col.format(value, row, cellCtx) : value);
408
+ const fallback = raw == null ? (col?.emptyText ?? "") : raw;
409
+ cellNodes = renderSlotToArray(slots, "cell", cellCtx, fallback);
410
+ }
411
+ if (!cellNodes.length) cellNodes = [""];
412
+ cellNodes.forEach((node) => td.appendChild(node));
413
+ tr.appendChild(td);
414
+ });
415
+
416
+ if (hasActions) {
417
+ const actionCtx = { ...rowCtx };
418
+ const actionRaw = typeof props.actions === "function" ? props.actions(row, rowCtx) : props.actions;
419
+ let actionNodes = renderSlotToArray(slots, "actions", actionCtx, actionRaw);
420
+ if (!actionNodes.length) actionNodes = renderSlotToArray(null, "default", actionCtx, actionRaw);
421
+ tr.appendChild(
422
+ _.td({ class: "jss-table-cell jss-table-cell-actions", style: { textAlign: "right" } },
423
+ _.div({ class: "jss-table-actions" }, ...actionNodes)
424
+ )
425
+ );
426
+ }
427
+
428
+ tbody.appendChild(tr);
429
+ }
430
+ }, "UI.Table:render");
431
+
432
+ wrapProps.body = shell;
433
+ const card = UI.Card(wrapProps);
434
+ JSswift._registerCleanup(card, stopRender);
435
+ if (stopSearchWatch) JSswift._registerCleanup(card, stopSearchWatch);
436
+ return card;
437
+ };
@@ -0,0 +1,212 @@
1
+ {
2
+ "status": "phase-1-closed",
3
+ "sourceOfTruth": "packages/ui/src/* + generated packages/ui/dist/ui.js",
4
+ "migrationRule": "Migrare una famiglia per volta, rigenerare il package UI con npm run build:ui e verificare demo/tutorial rilevanti.",
5
+ "buildOrder": [
6
+ "00-bootstrap.js",
7
+ "01-foundation-helpers.js",
8
+ "10-primitives-layout.js",
9
+ "20-display-content.js",
10
+ "21-list-content.js",
11
+ "22-banner-content.js",
12
+ "23-tooltip.js",
13
+ "31-form-advanced.js",
14
+ "40-navigation.js",
15
+ "50-feedback.js",
16
+ "60-shell-app.js",
17
+ "51-feedback-service.js",
18
+ "61-form-service.js",
19
+ "70-dialog.js",
20
+ "41-tab-panel.js",
21
+ "80-data.js",
22
+ "71-menu-overlays.js"
23
+ ],
24
+ "plannedFamilies": [
25
+ {
26
+ "file": "00-bootstrap.js",
27
+ "status": "migrated",
28
+ "scope": [
29
+ "IIFE initJSswiftUI",
30
+ "rod path proxy",
31
+ "base helper UI",
32
+ "token sets iniziali"
33
+ ]
34
+ },
35
+ {
36
+ "file": "01-foundation-helpers.js",
37
+ "status": "migrated",
38
+ "scope": [
39
+ "normalize args UI",
40
+ "helper shared UI",
41
+ "slot/meta shared helpers base",
42
+ "utility functions usate dai componenti"
43
+ ]
44
+ },
45
+ {
46
+ "file": "10-primitives-layout.js",
47
+ "status": "migrated",
48
+ "scope": [
49
+ "Row",
50
+ "Col",
51
+ "Spacer",
52
+ "Container",
53
+ "Card",
54
+ "Footer",
55
+ "Toolbar",
56
+ "Grid",
57
+ "GridCol"
58
+ ]
59
+ },
60
+ {
61
+ "file": "20-display-content.js",
62
+ "status": "migrated",
63
+ "scope": [
64
+ "Icon",
65
+ "Badge",
66
+ "Avatar",
67
+ "Chip"
68
+ ]
69
+ },
70
+ {
71
+ "file": "21-list-content.js",
72
+ "status": "migrated",
73
+ "scope": [
74
+ "List",
75
+ "Item",
76
+ "Separator"
77
+ ]
78
+ },
79
+ {
80
+ "file": "22-banner-content.js",
81
+ "status": "migrated",
82
+ "scope": [
83
+ "Banner"
84
+ ]
85
+ },
86
+ {
87
+ "file": "23-tooltip.js",
88
+ "status": "migrated",
89
+ "scope": [
90
+ "Tooltip"
91
+ ]
92
+ },
93
+ {
94
+ "file": "30-form-core.js",
95
+ "status": "merged-into-10-primitives-layout.js",
96
+ "scope": [
97
+ "FormField",
98
+ "InputRaw",
99
+ "Input",
100
+ "Textarea",
101
+ "Select"
102
+ ]
103
+ },
104
+ {
105
+ "file": "31-form-advanced.js",
106
+ "status": "migrated",
107
+ "scope": [
108
+ "Checkbox",
109
+ "Radio",
110
+ "Toggle",
111
+ "Slider",
112
+ "Rating",
113
+ "Date",
114
+ "Time",
115
+ "Form"
116
+ ]
117
+ },
118
+ {
119
+ "file": "40-navigation.js",
120
+ "status": "partial",
121
+ "scope": [
122
+ "Tabs",
123
+ "RouteTab",
124
+ "Breadcrumbs",
125
+ "Pagination"
126
+ ]
127
+ },
128
+ {
129
+ "file": "41-tab-panel.js",
130
+ "status": "migrated",
131
+ "scope": [
132
+ "TabPanel"
133
+ ]
134
+ },
135
+ {
136
+ "file": "50-feedback.js",
137
+ "status": "partial",
138
+ "scope": [
139
+ "Spinner",
140
+ "Progress",
141
+ "LoadingBar",
142
+ "Notify"
143
+ ]
144
+ },
145
+ {
146
+ "file": "51-feedback-service.js",
147
+ "status": "migrated",
148
+ "scope": [
149
+ "notify service wiring",
150
+ "toast root",
151
+ "toast timers",
152
+ "toast update/remove/clear/promise bridge"
153
+ ]
154
+ },
155
+ {
156
+ "file": "60-shell-app.js",
157
+ "status": "migrated",
158
+ "scope": [
159
+ "Header",
160
+ "Drawer",
161
+ "Page",
162
+ "AppShell",
163
+ "Parallax"
164
+ ]
165
+ },
166
+ {
167
+ "file": "61-form-service.js",
168
+ "status": "migrated",
169
+ "scope": [
170
+ "JSswift.form helpers",
171
+ "JSswift.useForm",
172
+ "Form",
173
+ "cardHeader",
174
+ "cardBody",
175
+ "cardFooter",
176
+ "dialog service bootstrap"
177
+ ]
178
+ },
179
+ {
180
+ "file": "70-dialog.js",
181
+ "status": "migrated",
182
+ "scope": [
183
+ "Dialog"
184
+ ]
185
+ },
186
+ {
187
+ "file": "80-data.js",
188
+ "status": "migrated",
189
+ "scope": [
190
+ "Table"
191
+ ]
192
+ },
193
+ {
194
+ "file": "71-menu-overlays.js",
195
+ "status": "migrated",
196
+ "scope": [
197
+ "Menu",
198
+ "Popover",
199
+ "ContextMenu",
200
+ "bundle footer"
201
+ ]
202
+ },
203
+ {
204
+ "file": "90-services-meta.js",
205
+ "status": "merged-into-51-feedback-service.js-and-61-form-service.js",
206
+ "scope": [
207
+ "notify service wiring",
208
+ "dialog helpers"
209
+ ]
210
+ }
211
+ ]
212
+ }