snice 7.8.0 → 7.9.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.
- package/README.md +1 -1
- package/adapters/react/SniceProvider.js +1 -1
- package/adapters/react/SniceRouter.js +1 -1
- package/adapters/react/matchRoute.js +1 -1
- package/adapters/react/table.d.ts +1 -0
- package/adapters/react/table.d.ts.map +1 -1
- package/adapters/react/table.js +1 -1
- package/adapters/react/table.js.map +1 -1
- package/adapters/react/table.tsx +2 -1
- package/adapters/react/useRequestHandler.js +1 -1
- package/bin/analyzer-contracts.js +17 -1
- package/custom-elements.json +57 -3
- package/dist/cdn/accordion/snice-accordion.js +1 -1
- package/dist/cdn/action-bar/snice-action-bar.js +1 -1
- package/dist/cdn/activity-feed/snice-activity-feed.js +1 -1
- package/dist/cdn/alert/snice-alert.js +1 -1
- package/dist/cdn/app-tiles/snice-app-tiles.js +1 -1
- package/dist/cdn/approval-flow/snice-approval-flow.js +1 -1
- package/dist/cdn/audio-recorder/snice-audio-recorder.js +1 -1
- package/dist/cdn/availability/snice-availability.js +1 -1
- package/dist/cdn/avatar/snice-avatar.js +1 -1
- package/dist/cdn/avatar-group/snice-avatar-group.js +1 -1
- package/dist/cdn/badge/snice-badge.js +1 -1
- package/dist/cdn/banner/snice-banner.js +1 -1
- package/dist/cdn/binpack/snice-binpack.js +1 -1
- package/dist/cdn/book/snice-book.js +1 -1
- package/dist/cdn/booking/snice-booking.js +1 -1
- package/dist/cdn/breadcrumbs/snice-breadcrumbs.js +1 -1
- package/dist/cdn/button/snice-button.js +1 -1
- package/dist/cdn/calendar/README.md +2 -2
- package/dist/cdn/calendar/snice-calendar.js +537 -44
- package/dist/cdn/calendar/snice-calendar.js.map +1 -1
- package/dist/cdn/calendar/snice-calendar.min.js +2 -2
- package/dist/cdn/calendar/snice-calendar.min.js.map +1 -1
- package/dist/cdn/camera/snice-camera.js +1 -1
- package/dist/cdn/camera-annotate/snice-camera-annotate.js +1 -1
- package/dist/cdn/candlestick/snice-candlestick.js +1 -1
- package/dist/cdn/card/snice-card.js +1 -1
- package/dist/cdn/carousel/snice-carousel.js +1 -1
- package/dist/cdn/cart/snice-cart.js +1 -1
- package/dist/cdn/chart/snice-chart.js +1 -1
- package/dist/cdn/chat/snice-chat.js +1 -1
- package/dist/cdn/checkbox/snice-checkbox.js +1 -1
- package/dist/cdn/chip/snice-chip.js +1 -1
- package/dist/cdn/code-block/README.md +2 -2
- package/dist/cdn/code-block/snice-code-block.js +177 -167
- package/dist/cdn/code-block/snice-code-block.js.map +1 -1
- package/dist/cdn/code-block/snice-code-block.min.js +2 -2
- package/dist/cdn/code-block/snice-code-block.min.js.map +1 -1
- package/dist/cdn/color-display/snice-color-display.js +1 -1
- package/dist/cdn/color-picker/snice-color-picker.js +1 -1
- package/dist/cdn/command-palette/README.md +1 -1
- package/dist/cdn/command-palette/snice-command-palette.js +2 -2
- package/dist/cdn/command-palette/snice-command-palette.js.map +1 -1
- package/dist/cdn/command-palette/snice-command-palette.min.js +1 -1
- package/dist/cdn/command-palette/snice-command-palette.min.js.map +1 -1
- package/dist/cdn/comments/snice-comments.js +1 -1
- package/dist/cdn/countdown/snice-countdown.js +1 -1
- package/dist/cdn/cropper/snice-cropper.js +1 -1
- package/dist/cdn/data-card/snice-data-card.js +1 -1
- package/dist/cdn/date-picker/snice-date-picker.js +1 -1
- package/dist/cdn/date-range-picker/snice-date-range-picker.js +1 -1
- package/dist/cdn/date-time-picker/snice-date-time-picker.js +1 -1
- package/dist/cdn/diff/snice-diff.js +1 -1
- package/dist/cdn/divider/snice-divider.js +1 -1
- package/dist/cdn/doc/snice-doc.js +1 -1
- package/dist/cdn/draw/snice-draw.js +1 -1
- package/dist/cdn/drawer/snice-drawer.js +1 -1
- package/dist/cdn/empty-state/snice-empty-state.js +1 -1
- package/dist/cdn/estimate/snice-estimate.js +1 -1
- package/dist/cdn/file-gallery/snice-file-gallery.js +1 -1
- package/dist/cdn/file-upload/snice-file-upload.js +1 -1
- package/dist/cdn/flip-card/snice-flip-card.js +1 -1
- package/dist/cdn/flow/snice-flow.js +1 -1
- package/dist/cdn/form-layout/snice-form-layout.js +1 -1
- package/dist/cdn/funnel/snice-funnel.js +1 -1
- package/dist/cdn/gantt/snice-gantt.js +1 -1
- package/dist/cdn/gauge/snice-gauge.js +1 -1
- package/dist/cdn/grid/snice-grid.js +1 -1
- package/dist/cdn/heatmap/snice-heatmap.js +1 -1
- package/dist/cdn/image/snice-image.js +1 -1
- package/dist/cdn/input/snice-input.js +1 -1
- package/dist/cdn/invoice/snice-invoice.js +1 -1
- package/dist/cdn/kanban/snice-kanban.js +1 -1
- package/dist/cdn/key-value/snice-key-value.js +1 -1
- package/dist/cdn/kpi/snice-kpi.js +1 -1
- package/dist/cdn/layout/snice-layout.js +1 -1
- package/dist/cdn/leaderboard/snice-leaderboard.js +1 -1
- package/dist/cdn/link/snice-link.js +1 -1
- package/dist/cdn/link-preview/snice-link-preview.js +1 -1
- package/dist/cdn/list/snice-list.js +1 -1
- package/dist/cdn/location/snice-location.js +1 -1
- package/dist/cdn/login/snice-login.js +1 -1
- package/dist/cdn/map/snice-map.js +1 -1
- package/dist/cdn/markdown/snice-markdown.js +1 -1
- package/dist/cdn/masonry/snice-masonry.js +1 -1
- package/dist/cdn/menu/snice-menu.js +1 -1
- package/dist/cdn/message-strip/snice-message-strip.js +1 -1
- package/dist/cdn/modal/snice-modal.js +1 -1
- package/dist/cdn/music-player/snice-music-player.js +1 -1
- package/dist/cdn/nav/snice-nav.js +1 -1
- package/dist/cdn/network-graph/snice-network-graph.js +1 -1
- package/dist/cdn/notification-center/snice-notification-center.js +1 -1
- package/dist/cdn/order-tracker/snice-order-tracker.js +1 -1
- package/dist/cdn/org-chart/snice-org-chart.js +1 -1
- package/dist/cdn/pagination/snice-pagination.js +1 -1
- package/dist/cdn/paint/snice-paint.js +1 -1
- package/dist/cdn/pdf-viewer/snice-pdf-viewer.js +1 -1
- package/dist/cdn/permission-matrix/snice-permission-matrix.js +1 -1
- package/dist/cdn/podcast-player/snice-podcast-player.js +1 -1
- package/dist/cdn/popover/snice-popover.js +1 -1
- package/dist/cdn/pricing-table/snice-pricing-table.js +1 -1
- package/dist/cdn/product-card/snice-product-card.js +1 -1
- package/dist/cdn/progress/snice-progress.js +2 -2
- package/dist/cdn/progress/snice-progress.js.map +1 -1
- package/dist/cdn/progress/snice-progress.min.js +1 -1
- package/dist/cdn/progress/snice-progress.min.js.map +1 -1
- package/dist/cdn/progress-ring/snice-progress-ring.js +1 -1
- package/dist/cdn/qr-code/README.md +2 -2
- package/dist/cdn/qr-code/snice-qr-code.js +19 -3
- package/dist/cdn/qr-code/snice-qr-code.js.map +1 -1
- package/dist/cdn/qr-code/snice-qr-code.min.js +2 -2
- package/dist/cdn/qr-code/snice-qr-code.min.js.map +1 -1
- package/dist/cdn/qr-reader/snice-qr-reader.js +1 -1
- package/dist/cdn/radio/snice-radio.js +1 -1
- package/dist/cdn/range-slider/snice-range-slider.js +1 -1
- package/dist/cdn/rating/snice-rating.js +1 -1
- package/dist/cdn/receipt/snice-receipt.js +5 -2
- package/dist/cdn/receipt/snice-receipt.js.map +1 -1
- package/dist/cdn/receipt/snice-receipt.min.js +1 -1
- package/dist/cdn/receipt/snice-receipt.min.js.map +1 -1
- package/dist/cdn/recipe/snice-recipe.js +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.js +4 -4
- package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.js +4 -4
- package/dist/cdn/runtime/snice-runtime.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
- package/dist/cdn/sankey/snice-sankey.js +1 -1
- package/dist/cdn/segmented-control/snice-segmented-control.js +1 -1
- package/dist/cdn/select/README.md +2 -2
- package/dist/cdn/select/snice-select.js +6 -9
- package/dist/cdn/select/snice-select.js.map +1 -1
- package/dist/cdn/select/snice-select.min.js +2 -2
- package/dist/cdn/select/snice-select.min.js.map +1 -1
- package/dist/cdn/skeleton/snice-skeleton.js +1 -1
- package/dist/cdn/slider/snice-slider.js +1 -1
- package/dist/cdn/sortable/snice-sortable.js +1 -1
- package/dist/cdn/sparkline/snice-sparkline.js +1 -1
- package/dist/cdn/spinner/snice-spinner.js +1 -1
- package/dist/cdn/split-button/snice-split-button.js +1 -1
- package/dist/cdn/split-pane/snice-split-pane.js +1 -1
- package/dist/cdn/spotlight/snice-spotlight.js +1 -1
- package/dist/cdn/stat-group/snice-stat-group.js +1 -1
- package/dist/cdn/step-input/snice-step-input.js +1 -1
- package/dist/cdn/stepper/snice-stepper.js +1 -1
- package/dist/cdn/switch/snice-switch.js +1 -1
- package/dist/cdn/table/README.md +2 -2
- package/dist/cdn/table/snice-table.esm.js +1940 -407
- package/dist/cdn/table/snice-table.esm.js.map +1 -1
- package/dist/cdn/table/snice-table.esm.min.js +242 -53
- package/dist/cdn/table/snice-table.esm.min.js.map +1 -1
- package/dist/cdn/table/snice-table.js +1940 -407
- package/dist/cdn/table/snice-table.js.map +1 -1
- package/dist/cdn/table/snice-table.min.js +234 -45
- package/dist/cdn/table/snice-table.min.js.map +1 -1
- package/dist/cdn/tabs/snice-tabs.js +1 -1
- package/dist/cdn/tag/snice-tag.js +1 -1
- package/dist/cdn/tag-input/snice-tag-input.js +1 -1
- package/dist/cdn/terminal/snice-terminal.js +1 -1
- package/dist/cdn/testimonial/snice-testimonial.js +1 -1
- package/dist/cdn/textarea/snice-textarea.js +1 -1
- package/dist/cdn/time-picker/snice-time-picker.js +1 -1
- package/dist/cdn/time-range-picker/snice-time-range-picker.js +1 -1
- package/dist/cdn/timeline/snice-timeline.js +1 -1
- package/dist/cdn/timer/snice-timer.js +1 -1
- package/dist/cdn/toast/snice-toast.js +1 -1
- package/dist/cdn/tooltip/snice-tooltip.js +1 -1
- package/dist/cdn/tree/snice-tree.js +1 -1
- package/dist/cdn/treemap/snice-treemap.js +1 -1
- package/dist/cdn/user-card/snice-user-card.js +1 -1
- package/dist/cdn/video-player/snice-video-player.js +1 -1
- package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +1 -1
- package/dist/cdn/waterfall/snice-waterfall.js +1 -1
- package/dist/cdn/weather/snice-weather.js +1 -1
- package/dist/cdn/work-order/snice-work-order.js +1 -1
- package/dist/components/calendar/snice-calendar.d.ts +187 -5
- package/dist/components/calendar/snice-calendar.js +537 -44
- package/dist/components/calendar/snice-calendar.js.map +1 -1
- package/dist/components/calendar/snice-calendar.types.d.ts +2 -1
- package/dist/components/code-block/formatter.d.ts +6 -0
- package/dist/components/code-block/formatter.js +174 -164
- package/dist/components/code-block/formatter.js.map +1 -1
- package/dist/components/code-block/grammars/snice.json +1 -1
- package/dist/components/code-block/grammars/typescript.json +1 -1
- package/dist/components/command-palette/snice-command-palette.js +1 -1
- package/dist/components/command-palette/snice-command-palette.js.map +1 -1
- package/dist/components/progress/snice-progress.js +1 -1
- package/dist/components/progress/snice-progress.js.map +1 -1
- package/dist/components/qr-code/qrcode.d.ts +1 -1
- package/dist/components/qr-code/qrcode.js +18 -2
- package/dist/components/qr-code/qrcode.js.map +1 -1
- package/dist/components/receipt/snice-receipt.js +4 -1
- package/dist/components/receipt/snice-receipt.js.map +1 -1
- package/dist/components/select/snice-select.d.ts +1 -1
- package/dist/components/select/snice-select.js +5 -8
- package/dist/components/select/snice-select.js.map +1 -1
- package/dist/components/table/snice-cell-actions.js +1 -1
- package/dist/components/table/snice-cell-actions.js.map +1 -1
- package/dist/components/table/snice-cell-color.js +1 -1
- package/dist/components/table/snice-cell-color.js.map +1 -1
- package/dist/components/table/snice-cell-date.js +20 -8
- package/dist/components/table/snice-cell-date.js.map +1 -1
- package/dist/components/table/snice-cell-email.js +1 -1
- package/dist/components/table/snice-cell-email.js.map +1 -1
- package/dist/components/table/snice-cell-image.js +1 -1
- package/dist/components/table/snice-cell-image.js.map +1 -1
- package/dist/components/table/snice-cell-json.js +1 -1
- package/dist/components/table/snice-cell-json.js.map +1 -1
- package/dist/components/table/snice-cell-link.js +1 -1
- package/dist/components/table/snice-cell-link.js.map +1 -1
- package/dist/components/table/snice-cell-location.js +1 -1
- package/dist/components/table/snice-cell-location.js.map +1 -1
- package/dist/components/table/snice-cell-phone.js +1 -1
- package/dist/components/table/snice-cell-phone.js.map +1 -1
- package/dist/components/table/snice-cell-status.js +1 -1
- package/dist/components/table/snice-cell-status.js.map +1 -1
- package/dist/components/table/snice-cell.d.ts +10 -0
- package/dist/components/table/snice-cell.js +59 -13
- package/dist/components/table/snice-cell.js.map +1 -1
- package/dist/components/table/snice-row.d.ts +0 -1
- package/dist/components/table/snice-row.js +4 -10
- package/dist/components/table/snice-row.js.map +1 -1
- package/dist/components/table/snice-table.d.ts +170 -2
- package/dist/components/table/snice-table.js +868 -189
- package/dist/components/table/snice-table.js.map +1 -1
- package/dist/components/table/snice-table.types.d.ts +17 -0
- package/dist/components/table/table-cell-presentation.d.ts +17 -4
- package/dist/components/table/table-cell-presentation.js +37 -11
- package/dist/components/table/table-cell-presentation.js.map +1 -1
- package/dist/components/table/table-column-manager.d.ts +153 -2
- package/dist/components/table/table-column-manager.js +364 -43
- package/dist/components/table/table-column-manager.js.map +1 -1
- package/dist/components/table/table-date.d.ts +29 -0
- package/dist/components/table/table-date.js +78 -0
- package/dist/components/table/table-date.js.map +1 -0
- package/dist/components/table/table-export.js +6 -2
- package/dist/components/table/table-export.js.map +1 -1
- package/dist/components/table/table-filter-engine.d.ts +9 -0
- package/dist/components/table/table-filter-engine.js +58 -14
- package/dist/components/table/table-filter-engine.js.map +1 -1
- package/dist/components/table/table-keyboard.d.ts +8 -0
- package/dist/components/table/table-keyboard.js +14 -3
- package/dist/components/table/table-keyboard.js.map +1 -1
- package/dist/components/table/table-toolbar.js +1 -0
- package/dist/components/table/table-toolbar.js.map +1 -1
- package/dist/components/table/table-tree-data.d.ts +2 -0
- package/dist/components/table/table-tree-data.js +35 -9
- package/dist/components/table/table-tree-data.js.map +1 -1
- package/dist/components/table/table-virtualizer.d.ts +44 -7
- package/dist/components/table/table-virtualizer.js +101 -54
- package/dist/components/table/table-virtualizer.js.map +1 -1
- package/dist/components/theme/theme.css +9 -0
- package/dist/index.cjs +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.iife.js +1 -1
- package/dist/react/SniceProvider.js +1 -1
- package/dist/react/SniceRouter.js +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/matchRoute.js +1 -1
- package/dist/react/useRequestHandler.js +1 -1
- package/dist/symbols.cjs +1 -1
- package/dist/symbols.esm.js +1 -1
- package/dist/testing-dom.cjs +1 -1
- package/dist/testing-dom.esm.js +1 -1
- package/dist/transitions.cjs +1 -1
- package/dist/transitions.esm.js +1 -1
- package/docs/ai/DEVELOPMENT.md +93 -2
- package/docs/ai/components/calendar.md +113 -10
- package/docs/ai/components/code-block.md +4 -0
- package/docs/ai/components/doc.md +1 -1
- package/docs/ai/components/progress.md +1 -0
- package/docs/ai/components/receipt.md +1 -1
- package/docs/ai/components/table.md +29 -30
- package/docs/ai/components/theme.md +1 -0
- package/docs/ai/events.md +30 -0
- package/docs/ai/theme.md +1 -0
- package/docs/components/calendar.md +171 -11
- package/docs/components/code-block.md +2 -0
- package/docs/components/doc.md +1 -1
- package/docs/components/progress.md +13 -0
- package/docs/components/receipt.md +1 -0
- package/docs/components/table.md +274 -15
- package/docs/components/theme.md +5 -0
- package/docs/events.md +49 -0
- package/docs/plans/2026-03-06-date-range-picker-plan.md +4 -4
- package/docs/plans/2026-03-07-table-mui-parity-design.md +1 -1
- package/docs/plans/2026-03-09-action-bar-plan.md +11 -11
- package/docs/superpowers/specs/2026-07-09-table-incredible-design.md +1 -1
- package/docs/superpowers/specs/2026-07-09-table-phase0-implementation.md +2 -2
- package/package.json +3 -1
- package/vscode.html-custom-data.json +13 -1
|
@@ -236,6 +236,22 @@ export type PaginationMode = 'client' | 'server';
|
|
|
236
236
|
* convention used across this file (attribute-reflectable, ergonomic to assign).
|
|
237
237
|
*/
|
|
238
238
|
export type SelectionMode = 'none' | 'single' | 'multiple';
|
|
239
|
+
/**
|
|
240
|
+
* How the columns relate to the width of the frame they are painted in.
|
|
241
|
+
*
|
|
242
|
+
* `scroll` (the default, and the historical behavior): a column never goes
|
|
243
|
+
* below its `minWidth`. A frame too narrow for the minimums overflows into the
|
|
244
|
+
* frame's own horizontal scroller, so every column keeps a readable width and
|
|
245
|
+
* the reader scrolls to the ones that did not fit.
|
|
246
|
+
*
|
|
247
|
+
* `squish`: the frame's width is the hard constraint and `minWidth` is relaxed
|
|
248
|
+
* to a bare legibility floor. Every visible column shares the frame, cell
|
|
249
|
+
* content ellipsises, and the table NEVER scrolls horizontally — the rightmost
|
|
250
|
+
* column edge sits on the frame's inner edge at any width. Resizing is still
|
|
251
|
+
* allowed; the columns beside the dragged one give up (or take back) the
|
|
252
|
+
* difference so the total stays inside the frame.
|
|
253
|
+
*/
|
|
254
|
+
export type ColumnFit = 'scroll' | 'squish';
|
|
239
255
|
/**
|
|
240
256
|
* The real public surface of `SniceTable` (components/table/snice-table.ts),
|
|
241
257
|
* enumerated directly from the class — every `@property`, every plain public
|
|
@@ -298,6 +314,7 @@ export interface SniceTableElement extends HTMLElement {
|
|
|
298
314
|
editable: boolean;
|
|
299
315
|
editMode: 'cell' | 'row';
|
|
300
316
|
density: 'compact' | 'standard' | 'comfortable';
|
|
317
|
+
columnFit: ColumnFit;
|
|
301
318
|
columnResize: boolean;
|
|
302
319
|
headerFilters: boolean;
|
|
303
320
|
quickFilter: boolean;
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
import type { ColumnDefinition } from './snice-table.types';
|
|
2
|
+
/** The alignment a column type renders with when the column declares none. */
|
|
3
|
+
export declare function defaultCellAlign(type?: string): 'left' | 'center' | 'right';
|
|
4
|
+
/**
|
|
5
|
+
* The value a typed cell holds when the row has nothing to show — the row field
|
|
6
|
+
* is null, or the row never carried the field at all.
|
|
7
|
+
*
|
|
8
|
+
* Each typed cell owns its value semantics: `false` for boolean, `0` for
|
|
9
|
+
* rating/progress/duration/filesize, `null` for JSON, `''` for the text-shaped
|
|
10
|
+
* rest. Handing every empty value the same `''` instead lets the cell's typed
|
|
11
|
+
* attribute converter re-read that empty string as a value of the wrong
|
|
12
|
+
* meaning — `''` on a Boolean property is an attribute that is *present*, i.e.
|
|
13
|
+
* `true`, and `''` on an Object property parses to `{}`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function emptyCellValue(type?: string): any;
|
|
2
16
|
/**
|
|
3
17
|
* Give every standalone specialized table cell the common ColumnDefinition
|
|
4
18
|
* presentation contract. The observer reapplies after Snice's differential
|
|
@@ -10,10 +24,9 @@ import type { ColumnDefinition } from './snice-table.types';
|
|
|
10
24
|
* fallback, so `formatter` wins. `formatterOverride` says the cell does NOT
|
|
11
25
|
* apply `column.formatter` itself, so this module owns both formatters for it.
|
|
12
26
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* renders structure rather than text, still shows the formatted string.
|
|
27
|
+
* Table-rendered cells never arrive here with a formatter: `createCellElement`
|
|
28
|
+
* resolves the pipeline once and hands the text cell the formatted string. This
|
|
29
|
+
* path serves the declarative and standalone cells, which own a full column.
|
|
17
30
|
*/
|
|
18
31
|
export declare function installCellPresentation(host: HTMLElement & {
|
|
19
32
|
column?: ColumnDefinition | null;
|
|
@@ -6,6 +6,37 @@ const presentationProperties = [
|
|
|
6
6
|
'fontSize',
|
|
7
7
|
'textDecoration',
|
|
8
8
|
];
|
|
9
|
+
/** The alignment a column type renders with when the column declares none. */
|
|
10
|
+
function defaultCellAlign(type) {
|
|
11
|
+
if (['number', 'currency', 'percent', 'percentage', 'duration', 'filesize',
|
|
12
|
+
'accounting', 'scientific', 'fraction'].includes(type || ''))
|
|
13
|
+
return 'right';
|
|
14
|
+
if (['boolean', 'rating', 'image'].includes(type || ''))
|
|
15
|
+
return 'center';
|
|
16
|
+
return 'left';
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The value a typed cell holds when the row has nothing to show — the row field
|
|
20
|
+
* is null, or the row never carried the field at all.
|
|
21
|
+
*
|
|
22
|
+
* Each typed cell owns its value semantics: `false` for boolean, `0` for
|
|
23
|
+
* rating/progress/duration/filesize, `null` for JSON, `''` for the text-shaped
|
|
24
|
+
* rest. Handing every empty value the same `''` instead lets the cell's typed
|
|
25
|
+
* attribute converter re-read that empty string as a value of the wrong
|
|
26
|
+
* meaning — `''` on a Boolean property is an attribute that is *present*, i.e.
|
|
27
|
+
* `true`, and `''` on an Object property parses to `{}`.
|
|
28
|
+
*/
|
|
29
|
+
function emptyCellValue(type) {
|
|
30
|
+
switch (type) {
|
|
31
|
+
case 'boolean': return false;
|
|
32
|
+
case 'rating':
|
|
33
|
+
case 'progress':
|
|
34
|
+
case 'duration':
|
|
35
|
+
case 'filesize': return 0;
|
|
36
|
+
case 'json': return null;
|
|
37
|
+
default: return '';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
9
40
|
const installed = new WeakMap();
|
|
10
41
|
const appliedClasses = new WeakMap();
|
|
11
42
|
/**
|
|
@@ -19,10 +50,9 @@ const appliedClasses = new WeakMap();
|
|
|
19
50
|
* fallback, so `formatter` wins. `formatterOverride` says the cell does NOT
|
|
20
51
|
* apply `column.formatter` itself, so this module owns both formatters for it.
|
|
21
52
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* renders structure rather than text, still shows the formatted string.
|
|
53
|
+
* Table-rendered cells never arrive here with a formatter: `createCellElement`
|
|
54
|
+
* resolves the pipeline once and hands the text cell the formatted string. This
|
|
55
|
+
* path serves the declarative and standalone cells, which own a full column.
|
|
26
56
|
*/
|
|
27
57
|
function installCellPresentation(host, formatterOverride = false) {
|
|
28
58
|
if (installed.has(host))
|
|
@@ -75,12 +105,8 @@ function installCellPresentation(host, formatterOverride = false) {
|
|
|
75
105
|
const formatter = column.formatter
|
|
76
106
|
? (formatterOverride ? column.formatter : null)
|
|
77
107
|
: column.valueFormatter;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const display = host.hasAttribute('formatted')
|
|
81
|
-
? (host.getAttribute('value') ?? '')
|
|
82
|
-
: (formatter ? String(formatter(host.value, host.rowData) ?? '') : null);
|
|
83
|
-
if (display !== null) {
|
|
108
|
+
if (formatter) {
|
|
109
|
+
const display = String(formatter(host.value, host.rowData) ?? '');
|
|
84
110
|
const content = host.shadowRoot?.querySelector('[part~="content"]');
|
|
85
111
|
if (content && (content.textContent !== display || content.childElementCount > 0)) {
|
|
86
112
|
content.textContent = display;
|
|
@@ -101,5 +127,5 @@ function installCellPresentation(host, formatterOverride = false) {
|
|
|
101
127
|
queueMicrotask(sync);
|
|
102
128
|
}
|
|
103
129
|
|
|
104
|
-
export { installCellPresentation };
|
|
130
|
+
export { defaultCellAlign, emptyCellValue, installCellPresentation };
|
|
105
131
|
//# sourceMappingURL=table-cell-presentation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-cell-presentation.js","sources":["../../../../components/table/table-cell-presentation.ts"],"sourcesContent":["import type { ColumnDefinition, CellStyle } from './snice-table.types';\n\nconst presentationProperties: Array<keyof CellStyle> = [\n 'backgroundColor',\n 'color',\n 'fontWeight',\n 'fontStyle',\n 'fontSize',\n 'textDecoration',\n];\n\nconst installed = new WeakMap<HTMLElement, MutationObserver>();\nconst appliedClasses = new WeakMap<HTMLElement, string[]>();\n\n/**\n * Give every standalone specialized table cell the common ColumnDefinition\n * presentation contract. The observer reapplies after Snice's differential\n * renderer changes shadow content; equality guards prevent mutation loops.\n *\n * Display formatters\n * ------------------\n * `formatter` is the column's display formatter and `valueFormatter` its\n * fallback, so `formatter` wins. `formatterOverride` says the cell does NOT\n * apply `column.formatter` itself, so this module owns both formatters for it.\n *\n *
|
|
1
|
+
{"version":3,"file":"table-cell-presentation.js","sources":["../../../../components/table/table-cell-presentation.ts"],"sourcesContent":["import type { ColumnDefinition, CellStyle } from './snice-table.types';\n\nconst presentationProperties: Array<keyof CellStyle> = [\n 'backgroundColor',\n 'color',\n 'fontWeight',\n 'fontStyle',\n 'fontSize',\n 'textDecoration',\n];\n\n/** The alignment a column type renders with when the column declares none. */\nexport function defaultCellAlign(type?: string): 'left' | 'center' | 'right' {\n if (['number', 'currency', 'percent', 'percentage', 'duration', 'filesize',\n 'accounting', 'scientific', 'fraction'].includes(type || '')) return 'right';\n if (['boolean', 'rating', 'image'].includes(type || '')) return 'center';\n return 'left';\n}\n\n/**\n * The value a typed cell holds when the row has nothing to show — the row field\n * is null, or the row never carried the field at all.\n *\n * Each typed cell owns its value semantics: `false` for boolean, `0` for\n * rating/progress/duration/filesize, `null` for JSON, `''` for the text-shaped\n * rest. Handing every empty value the same `''` instead lets the cell's typed\n * attribute converter re-read that empty string as a value of the wrong\n * meaning — `''` on a Boolean property is an attribute that is *present*, i.e.\n * `true`, and `''` on an Object property parses to `{}`.\n */\nexport function emptyCellValue(type?: string): any {\n switch (type) {\n case 'boolean': return false;\n case 'rating':\n case 'progress':\n case 'duration':\n case 'filesize': return 0;\n case 'json': return null;\n default: return '';\n }\n}\n\nconst installed = new WeakMap<HTMLElement, MutationObserver>();\nconst appliedClasses = new WeakMap<HTMLElement, string[]>();\n\n/**\n * Give every standalone specialized table cell the common ColumnDefinition\n * presentation contract. The observer reapplies after Snice's differential\n * renderer changes shadow content; equality guards prevent mutation loops.\n *\n * Display formatters\n * ------------------\n * `formatter` is the column's display formatter and `valueFormatter` its\n * fallback, so `formatter` wins. `formatterOverride` says the cell does NOT\n * apply `column.formatter` itself, so this module owns both formatters for it.\n *\n * Table-rendered cells never arrive here with a formatter: `createCellElement`\n * resolves the pipeline once and hands the text cell the formatted string. This\n * path serves the declarative and standalone cells, which own a full column.\n */\nexport function installCellPresentation(\n host: HTMLElement & { column?: ColumnDefinition | null; value?: any; rowData?: any },\n formatterOverride = false,\n) {\n if (installed.has(host)) return;\n let observer: MutationObserver | null = null;\n let syncing = false;\n\n const sync = () => {\n if (syncing) return;\n syncing = true;\n observer?.disconnect();\n try {\n const column = host.column;\n for (const className of appliedClasses.get(host) || []) host.classList.remove(className);\n appliedClasses.set(host, []);\n for (const property of presentationProperties) (host.style as any)[property] = '';\n host.removeAttribute('title');\n if (!column) return;\n\n const applyStyle = (style?: CellStyle) => {\n if (!style) return;\n for (const property of presentationProperties) {\n const value = style[property];\n if (value) (host.style as any)[property] = value;\n }\n };\n\n applyStyle(column.style);\n for (const rule of column.conditionalFormats || []) {\n if (!rule.condition(host.value, host.rowData)) continue;\n applyStyle(rule.style);\n if (rule.className) {\n host.classList.add(rule.className);\n appliedClasses.set(host, [rule.className]);\n }\n break;\n }\n\n if (column.tooltip) {\n host.title = typeof column.tooltip === 'function'\n ? column.tooltip(host.value, host.rowData)\n : (host.value == null ? '' : String(host.value));\n }\n\n // `formatter` beats `valueFormatter`. A cell that applies `formatter`\n // itself has already painted it, so the fallback must not overwrite that\n // content — only a formatter-less column falls through to valueFormatter.\n const formatter = column.formatter\n ? (formatterOverride ? column.formatter : null)\n : column.valueFormatter;\n if (formatter) {\n const display = String(formatter(host.value, host.rowData) ?? '');\n const content = host.shadowRoot?.querySelector('[part~=\"content\"]') as HTMLElement | null;\n if (content && (content.textContent !== display || content.childElementCount > 0)) {\n content.textContent = display;\n }\n }\n } finally {\n syncing = false;\n if (observer && host.shadowRoot) {\n observer.observe(host.shadowRoot, { childList: true, subtree: true, characterData: true });\n }\n }\n };\n\n observer = new MutationObserver(sync);\n if (host.shadowRoot) observer.observe(host.shadowRoot, { childList: true, subtree: true, characterData: true });\n installed.set(host, observer);\n queueMicrotask(sync);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
* Column management for snice-table.
|
|
3
3
|
* Handles: flex width, resize, auto-size, visibility, ordering, pinning, groups.
|
|
4
4
|
*/
|
|
5
|
-
import type { ColumnDefinition } from './snice-table.types';
|
|
5
|
+
import type { ColumnDefinition, ColumnFit } from './snice-table.types';
|
|
6
|
+
/** Padding + border a cell spends before any content fits inside it. */
|
|
7
|
+
export declare function horizontalCellChrome(cell: HTMLElement): number;
|
|
6
8
|
export interface ColumnState {
|
|
7
9
|
key: string;
|
|
8
10
|
width: number;
|
|
@@ -16,6 +18,13 @@ export interface ColumnState {
|
|
|
16
18
|
reorderable: boolean;
|
|
17
19
|
hideable: boolean;
|
|
18
20
|
pinnable: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Someone chose this width on purpose — the column definition declared one,
|
|
23
|
+
* the user dragged the edge, or auto-size measured the content. Only columns
|
|
24
|
+
* that never did participate in `fitVisibleColumns`, so a deliberate width is
|
|
25
|
+
* never quietly overwritten by the container's arithmetic.
|
|
26
|
+
*/
|
|
27
|
+
authored: boolean;
|
|
19
28
|
}
|
|
20
29
|
export interface ColumnGroup {
|
|
21
30
|
label: string;
|
|
@@ -30,8 +39,71 @@ export declare class TableColumnManager {
|
|
|
30
39
|
private resizingKey;
|
|
31
40
|
private resizeOverlay;
|
|
32
41
|
private tableElement;
|
|
33
|
-
|
|
42
|
+
private fitMode;
|
|
43
|
+
/**
|
|
44
|
+
* The content budget the last `squish` fit shared out. A drag-resize needs it
|
|
45
|
+
* to know how much width the columns beside the dragged one have to give up
|
|
46
|
+
* (or take back) for the total to stay on the frame.
|
|
47
|
+
*/
|
|
48
|
+
private squishBudget;
|
|
49
|
+
/** Fallback content width for a column nobody sized. */
|
|
50
|
+
static readonly DEFAULT_WIDTH = 150;
|
|
51
|
+
/**
|
|
52
|
+
* The floor `squish` relaxes `minWidth` down to. Not zero: a column narrower
|
|
53
|
+
* than this shows no glyph at all, only its ellipsis, and stops being a
|
|
54
|
+
* column the reader can identify. A frame too narrow even for this is past
|
|
55
|
+
* what the mode can honour — see `fitVisibleColumns`.
|
|
56
|
+
*/
|
|
57
|
+
static readonly SQUISH_MIN_WIDTH = 24;
|
|
58
|
+
/**
|
|
59
|
+
* Which fitting policy `fitVisibleColumns` (and a drag-resize) follows.
|
|
60
|
+
* Owned by the table's `columnFit` property; see the `ColumnFit` docs.
|
|
61
|
+
*/
|
|
62
|
+
setFitMode(mode: ColumnFit): void;
|
|
63
|
+
getFitMode(): ColumnFit;
|
|
64
|
+
/**
|
|
65
|
+
* Routine resync, run on every render: make sure a state exists for each
|
|
66
|
+
* declared column and refresh the flags that are pure declaration (min/max,
|
|
67
|
+
* resizable, reorderable, hideable, pinnable, flex).
|
|
68
|
+
*
|
|
69
|
+
* Deliberately PRESERVES the interaction-owned members of an existing state —
|
|
70
|
+
* width, visible, pinned, order — because renderBody() calls this on every
|
|
71
|
+
* paint, and re-applying the declaration here would undo a drag-resize, a
|
|
72
|
+
* hidden column or a user reorder on the very next render. Re-applying the
|
|
73
|
+
* declaration is applyConfiguration()'s job, and only a `columns` assignment
|
|
74
|
+
* calls that.
|
|
75
|
+
*/
|
|
34
76
|
initialize(columns: ColumnDefinition[], tableEl: HTMLElement): void;
|
|
77
|
+
/**
|
|
78
|
+
* A `columns` assignment (or setColumns()) delivered a NEW CONFIGURATION.
|
|
79
|
+
*
|
|
80
|
+
* The declaration is the source of truth here: painted order, `pinned`,
|
|
81
|
+
* `width` and visibility all come from the array just assigned, and states for
|
|
82
|
+
* columns the new array no longer declares are DROPPED. Without this the first
|
|
83
|
+
* configuration the table ever saw won permanently — a re-ordered array kept
|
|
84
|
+
* the original order, a newly declared pin or width was ignored, and a column
|
|
85
|
+
* hidden through setColumnVisible() could never be brought back
|
|
86
|
+
* (MATRIX-columns-2/3/4/6).
|
|
87
|
+
*
|
|
88
|
+
* The cost is that the assignment also discards user interaction state (a
|
|
89
|
+
* drag-resize, a manual reorder, a hidden column) for the columns it
|
|
90
|
+
* re-declares. That is the intended reading of the contract, and it applies to
|
|
91
|
+
* EVERY assignment: `columns` declares `hasChanged: () => true`, so handing
|
|
92
|
+
* back the array the table already holds — after mutating it, or unchanged —
|
|
93
|
+
* re-applies the declaration exactly like a fresh array would. Mutating the
|
|
94
|
+
* published definitions is therefore NOT an escape hatch; the only way to keep
|
|
95
|
+
* user column state is to not assign `columns` at all and drive the change
|
|
96
|
+
* through the column APIs instead (setColumnVisible / moveColumn / pinColumn /
|
|
97
|
+
* unpinColumn), which mutate the state map in place. Renders triggered by this
|
|
98
|
+
* go through the table's coalescing queue, so re-applying costs no extra paint.
|
|
99
|
+
*/
|
|
100
|
+
applyConfiguration(columns: ColumnDefinition[], tableEl: HTMLElement): void;
|
|
101
|
+
/**
|
|
102
|
+
* One place that turns a column definition into a state. `existing` supplies
|
|
103
|
+
* the interaction-owned members on the resync path; omitting it yields the
|
|
104
|
+
* pure declared state applyConfiguration() wants.
|
|
105
|
+
*/
|
|
106
|
+
private buildState;
|
|
35
107
|
private parseWidth;
|
|
36
108
|
/** Get ordered, visible columns */
|
|
37
109
|
getVisibleColumns(): ColumnState[];
|
|
@@ -45,6 +117,63 @@ export declare class TableColumnManager {
|
|
|
45
117
|
getUnpinned(): ColumnState[];
|
|
46
118
|
/** Compute flex widths based on available space */
|
|
47
119
|
computeFlexWidths(availableWidth: number): Map<string, number>;
|
|
120
|
+
/**
|
|
121
|
+
* Fit the columns nobody sized into `availableWidth` (the frame's content
|
|
122
|
+
* box), reserving `chromePerColumn` for each column's own padding + border.
|
|
123
|
+
*
|
|
124
|
+
* A column width is a CONTENT width — the rendered column is that plus its
|
|
125
|
+
* chrome — so the budget has to come off the top or the fitted table lands a
|
|
126
|
+
* few pixels wider than the frame it was fitted to.
|
|
127
|
+
*
|
|
128
|
+
* Declared and user-chosen widths are spent first and never rewritten: a
|
|
129
|
+
* table that asked for `width: '80'` keeps 80 whatever the frame does. What
|
|
130
|
+
* is left is split evenly and clamped to each column's [minWidth, maxWidth],
|
|
131
|
+
* so a frame too narrow for the minimums overflows into the frame's own
|
|
132
|
+
* scroller instead of collapsing the columns to nothing.
|
|
133
|
+
*
|
|
134
|
+
* Returns whether any width actually moved, so callers can skip a repaint.
|
|
135
|
+
*
|
|
136
|
+
* Under `column-fit="squish"` the frame stops being a suggestion: see
|
|
137
|
+
* `squishVisibleColumns`.
|
|
138
|
+
*/
|
|
139
|
+
fitVisibleColumns(availableWidth: number, chromePerColumn?: number): boolean;
|
|
140
|
+
/**
|
|
141
|
+
* The `squish` policy: the columns add up to the frame, whatever that costs.
|
|
142
|
+
*
|
|
143
|
+
* `minWidth` is a readability preference, and this mode has already decided
|
|
144
|
+
* the frame outranks it, so the only floor left is SQUISH_MIN_WIDTH. Two
|
|
145
|
+
* cases:
|
|
146
|
+
*
|
|
147
|
+
* - There is an unsized column left to absorb the difference, and the
|
|
148
|
+
* authored widths still leave room for it. Those are honoured exactly (a
|
|
149
|
+
* column that asked for 80, or that the user dragged to 80, keeps 80) and
|
|
150
|
+
* the rest is split evenly between the unsized ones.
|
|
151
|
+
*
|
|
152
|
+
* - Every column is authored, or the authored widths alone already overflow
|
|
153
|
+
* the frame. There is nothing left to give, so `scroll`'s escape hatch
|
|
154
|
+
* (overflow into the frame's scroller) is exactly what this mode exists to
|
|
155
|
+
* prevent: every column is scaled by the same factor instead. Scaling is a
|
|
156
|
+
* fixed point — the second pass computes a factor of 1 — so this settles
|
|
157
|
+
* on the first render rather than creeping on every repaint.
|
|
158
|
+
*
|
|
159
|
+
* Either way the remainder from integer division is handed back to the widest
|
|
160
|
+
* columns that are free to take it, so the widths sum to the budget EXACTLY
|
|
161
|
+
* and the rightmost column edge lands on the frame's inner edge instead of a
|
|
162
|
+
* few pixels short of it.
|
|
163
|
+
*/
|
|
164
|
+
private squishVisibleColumns;
|
|
165
|
+
/**
|
|
166
|
+
* A drag-resize under `squish` moved one column; the others pay for it.
|
|
167
|
+
*
|
|
168
|
+
* The dragged column is the anchor — it keeps the width the pointer asked
|
|
169
|
+
* for, capped so the remaining columns can still sit on their floor — and the
|
|
170
|
+
* rest are scaled to fill exactly what is left of the frame. Without this a
|
|
171
|
+
* drag would simply push the trailing column out of a frame that is not
|
|
172
|
+
* allowed to scroll.
|
|
173
|
+
*/
|
|
174
|
+
private rebalanceSquish;
|
|
175
|
+
/** Push the current widths onto the painted header and body cells. */
|
|
176
|
+
private writeWidths;
|
|
48
177
|
/** Apply computed widths to <col> or <th> elements */
|
|
49
178
|
applyWidths(headerRow: HTMLElement, widths: Map<string, number>): void;
|
|
50
179
|
/** Start column resize. Call from mousedown on resize handle. */
|
|
@@ -53,6 +182,28 @@ export declare class TableColumnManager {
|
|
|
53
182
|
autoSizeColumn(columnKey: string, tbody: HTMLElement): void;
|
|
54
183
|
/** Auto-size all columns */
|
|
55
184
|
autoSizeAll(tbody: HTMLElement): void;
|
|
185
|
+
/** Slack added to a measured content width so the last glyph never sits on
|
|
186
|
+
* the clip edge (and a sortable header keeps room for its chevron). */
|
|
187
|
+
private static readonly AUTO_SIZE_SLACK;
|
|
188
|
+
/**
|
|
189
|
+
* Measure the columns' content and give each the width it actually needs.
|
|
190
|
+
*
|
|
191
|
+
* A table cell's `scrollWidth` is NOT its content width: for content that
|
|
192
|
+
* fits, it reports the padding box — the width the column already has. The
|
|
193
|
+
* previous implementation took that maximum and added 16px, so every
|
|
194
|
+
* "auto-size" pass could only GROW the column, by a chrome's worth each
|
|
195
|
+
* time, until the table outgrew its own frame. Once it did, the right-pinned
|
|
196
|
+
* column (`position: sticky`) parked over the columns beside it, and the
|
|
197
|
+
* columns behind it read as deleted.
|
|
198
|
+
*
|
|
199
|
+
* The width a column NEEDS is a layout question, so ask layout: drop the
|
|
200
|
+
* table into content-driven sizing (`table-layout: auto` at `max-content`)
|
|
201
|
+
* with the measured columns' imposed widths removed, and read back the width
|
|
202
|
+
* each header settles at. `max-content` also means no wrapping, so a long
|
|
203
|
+
* cell reports its full single-line extent even though the painted column
|
|
204
|
+
* ellipsises it. Everything is restored in the same task, before paint.
|
|
205
|
+
*/
|
|
206
|
+
private autoSizeColumns;
|
|
56
207
|
setColumnVisible(key: string, visible: boolean): void;
|
|
57
208
|
showAllColumns(): void;
|
|
58
209
|
hideAllColumns(): void;
|