@synopackageland/ui 0.20.3 → 0.20.4

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 (146) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSES/ux-foundation.md +83 -0
  3. package/LICENSES/ux-grid-baserow.md +35 -0
  4. package/LICENSES/ux-grid-teable.md +48 -0
  5. package/README.md +3 -0
  6. package/dist/cli.js +0 -0
  7. package/dist/components/app/app-layout/AppLayout.vue.d.ts +31 -4
  8. package/dist/components/app/app-root/AppRoot.vue.d.ts +9 -0
  9. package/dist/components/app/aside-panel/AsidePanel.vue.d.ts +69 -0
  10. package/dist/components/app/aside-panel/asidePreference.d.ts +28 -0
  11. package/dist/components/composite/adaptive-panel/AdaptivePanel.vue.d.ts +61 -0
  12. package/dist/components/composite/connection-topology/ConnectionTopology.vue.d.ts +1 -1
  13. package/dist/components/composite/file-picker/FilePicker.vue.d.ts +1 -1
  14. package/dist/components/composite/mention-list/MentionList.vue.d.ts +2 -2
  15. package/dist/components/composite/overflow-toolbar/OverflowToolbar.vue.d.ts +2 -2
  16. package/dist/components/composite/record-panel/RecordPanel.vue.d.ts +77 -0
  17. package/dist/components/composite/record-panel/recordPanelWidth.d.ts +54 -0
  18. package/dist/components/composite/summary-card/SummaryCard.vue.d.ts +1 -1
  19. package/dist/components/composite/tag-editor/TagEditor.vue.d.ts +2 -2
  20. package/dist/components/composite/tree-view/TreeView.vue.d.ts +1 -1
  21. package/dist/components/composite/wizard/Wizard.vue.d.ts +2 -2
  22. package/dist/components/composite/wizard/WizardDialog.vue.d.ts +2 -2
  23. package/dist/components/containers/card/Card.vue.d.ts +1 -1
  24. package/dist/components/containers/card/CardField.vue.d.ts +26 -0
  25. package/dist/components/containers/card-grid/CardCover.vue.d.ts +16 -0
  26. package/dist/components/containers/card-grid/CardGrid.vue.d.ts +1 -1
  27. package/dist/components/containers/card-grid/VirtualCardGrid.vue.d.ts +71 -0
  28. package/dist/components/containers/expandable-item/ExpandableItem.vue.d.ts +1 -1
  29. package/dist/components/containers/fieldset/Fieldset.vue.d.ts +1 -1
  30. package/dist/components/containers/list-detail/ListDetail.vue.d.ts +1 -1
  31. package/dist/components/containers/split-pane/SplitPane.vue.d.ts +1 -1
  32. package/dist/components/feedback/notification/Notification.vue.d.ts +1 -1
  33. package/dist/components/feedback/notification/NotificationProvider.vue.d.ts +1 -1
  34. package/dist/components/primitives/breadcrumb/Breadcrumb.vue.d.ts +2 -2
  35. package/dist/components/primitives/context-menu/ContextMenu.vue.d.ts +3 -0
  36. package/dist/components/primitives/context-menu/ContextMenuItems.vue.d.ts +4 -5
  37. package/dist/components/primitives/dialog/Dialog.vue.d.ts +2 -2
  38. package/dist/components/primitives/dropdown-menu/DropdownMenu.vue.d.ts +4 -0
  39. package/dist/components/primitives/dropdown-menu/DropdownMenuItems.vue.d.ts +6 -3
  40. package/dist/components/primitives/popover/Popover.vue.d.ts +10 -2
  41. package/dist/components/primitives/popover/floating.d.ts +27 -0
  42. package/dist/components/primitives/popover/overlay.d.ts +36 -0
  43. package/dist/components/primitives/segment-control/SegmentControl.vue.d.ts +4 -1
  44. package/dist/components/primitives/segment-control/context.d.ts +3 -0
  45. package/dist/components/primitives/select/Select.vue.d.ts +4 -0
  46. package/dist/components/primitives/select/internal/ComboboxField.vue.d.ts +1 -0
  47. package/dist/components/primitives/select/internal/types.d.ts +2 -0
  48. package/dist/components/primitives/skeleton/SectionSkeleton.vue.d.ts +25 -4
  49. package/dist/components/primitives/skeleton/Skeleton.vue.d.ts +3 -0
  50. package/dist/components/primitives/tag/Tag.vue.d.ts +2 -2
  51. package/dist/components/primitives/toast/ToastProvider.vue.d.ts +0 -2
  52. package/dist/components/primitives/toast/toast.d.ts +21 -1
  53. package/dist/components/primitives/tooltip/Tooltip.vue.d.ts +8 -3
  54. package/dist/components/primitives/tooltip/tooltipStyle.d.ts +11 -1
  55. package/dist/composables/backDismiss.d.ts +19 -0
  56. package/dist/composables/phone.d.ts +8 -0
  57. package/dist/composables/softKeyboard.d.ts +26 -4
  58. package/dist/composables/visualViewport.d.ts +31 -0
  59. package/dist/dnd/autoScroll.d.ts +57 -0
  60. package/dist/dnd/dragKit.d.ts +111 -0
  61. package/dist/dnd/index.d.ts +4 -0
  62. package/dist/dnd/layout.d.ts +57 -0
  63. package/dist/dnd/vue.d.ts +16 -0
  64. package/dist/feedback/StatusSlot.vue.d.ts +24 -0
  65. package/dist/feedback/showAfter.d.ts +15 -0
  66. package/dist/feedback/stackMotion.d.ts +13 -0
  67. package/dist/feedback/timing.d.ts +23 -0
  68. package/dist/grid/cells/draw.d.ts +57 -0
  69. package/dist/grid/cells/images.d.ts +5 -0
  70. package/dist/grid/cells/index.d.ts +7 -0
  71. package/dist/grid/cells/number.d.ts +5 -0
  72. package/dist/grid/cells/registry.d.ts +56 -0
  73. package/dist/grid/cells/renderers.d.ts +8 -0
  74. package/dist/grid/cells/status.d.ts +6 -0
  75. package/dist/grid/cells/types.d.ts +200 -0
  76. package/dist/grid/cells/use.d.ts +7 -0
  77. package/dist/grid/clipboard/copy.d.ts +17 -0
  78. package/dist/grid/clipboard/index.d.ts +4 -0
  79. package/dist/grid/clipboard/proposal.d.ts +35 -0
  80. package/dist/grid/clipboard/tsv.d.ts +14 -0
  81. package/dist/grid/clipboard/write.d.ts +21 -0
  82. package/dist/grid/contracts.d.ts +200 -0
  83. package/dist/grid/edit/cell-status.d.ts +33 -0
  84. package/dist/grid/edit/edit-session.d.ts +97 -0
  85. package/dist/grid/edit/use-grid-edit.d.ts +48 -0
  86. package/dist/grid/focus/editor-style.d.ts +67 -0
  87. package/dist/grid/host/GridHost.vue.d.ts +137 -0
  88. package/dist/grid/host/controller.d.ts +219 -0
  89. package/dist/grid/host/dom.d.ts +10 -0
  90. package/dist/grid/index.d.ts +8 -0
  91. package/dist/grid/range/block.d.ts +30 -0
  92. package/dist/grid/range/fill.d.ts +27 -0
  93. package/dist/grid/range/index.d.ts +2 -0
  94. package/dist/grid/theme.d.ts +61 -0
  95. package/dist/grid-core/auto-scroll.d.ts +67 -0
  96. package/dist/grid-core/column-resize.d.ts +43 -0
  97. package/dist/grid-core/config.d.ts +39 -0
  98. package/dist/grid-core/coordinate.d.ts +64 -0
  99. package/dist/grid-core/drag.d.ts +46 -0
  100. package/dist/grid-core/freeze.d.ts +11 -0
  101. package/dist/grid-core/index.d.ts +17 -0
  102. package/dist/grid-core/keyboard.d.ts +34 -0
  103. package/dist/grid-core/keys.d.ts +38 -0
  104. package/dist/grid-core/lru.d.ts +10 -0
  105. package/dist/grid-core/range.d.ts +28 -0
  106. package/dist/grid-core/region.d.ts +73 -0
  107. package/dist/grid-core/renderer/base.d.ts +92 -0
  108. package/dist/grid-core/renderer/layout.d.ts +129 -0
  109. package/dist/grid-core/selection-controller.d.ts +62 -0
  110. package/dist/grid-core/selection.d.ts +35 -0
  111. package/dist/grid-core/theme.d.ts +81 -0
  112. package/dist/grid-core/types.d.ts +178 -0
  113. package/dist/grid.js +6173 -0
  114. package/dist/i18n/text.d.ts +6 -0
  115. package/dist/index.d.ts +32 -2
  116. package/dist/index.js +17647 -13630
  117. package/dist/interaction/editSession.d.ts +49 -0
  118. package/dist/interaction/focus.d.ts +28 -0
  119. package/dist/interaction/gesture.d.ts +49 -0
  120. package/dist/interaction/ime.d.ts +55 -0
  121. package/dist/interaction/index.d.ts +6 -0
  122. package/dist/interaction/outside.d.ts +40 -0
  123. package/dist/interaction/vue.d.ts +21 -0
  124. package/dist/json-ai-prompt.md +1 -1
  125. package/dist/json-preview/preview.js +8523 -7814
  126. package/dist/json.js +10 -10
  127. package/dist/lib/adaptiveLayout.d.ts +32 -2
  128. package/dist/lib/deviceViewport.d.ts +2 -1
  129. package/dist/lib/motion.d.ts +12 -0
  130. package/dist/reka-runtime.json +1 -1
  131. package/dist/theme.css +1 -1
  132. package/dist/themes/dsm7-embedded-theme.css +1 -1
  133. package/dist/themes/dsm7-embedded.css +1 -1
  134. package/dist/themes/dsm7.css +1 -1
  135. package/dist/virtual/cardHeight.d.ts +39 -0
  136. package/dist/virtual/galleryColumns.d.ts +11 -0
  137. package/dist/virtual/layoutMotion.d.ts +30 -0
  138. package/docs/adaptive-layout.md +137 -16
  139. package/docs/callout.md +22 -1
  140. package/docs/list-detail.md +54 -0
  141. package/docs/mobile-native.md +214 -0
  142. package/docs/release-checks.md +23 -0
  143. package/docs/theme-hooks.md +28 -7
  144. package/docs/ux-foundation.md +133 -0
  145. package/docs/ux-grid.md +217 -0
  146. package/package.json +94 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.20.4 (2026-11-05)
4
+
5
+ - Keep anchored menus, pickers and tips within the shared floating boundary, safe area and keyboard inset
6
+ - On a phone, toasts sit at the bottom full width above the tab bar or keyboard, swipe down and show one at a time; notifications sit full width at the top. Hover-only card actions, the ScheduleTable pen and the TypoHeader anchor show at rest without hover, and a 250ms press opens a card's menu
7
+
8
+ - Compact chrome is the only density: web chrome rows 48px (window and phone keep 44px), chrome controls 28px, header actions 32px, web navigation rows 32px, icons 16px. The `web` presentation uses the system font stack (no Inter)
9
+ - Final motion tokens: fast 150ms, normal 200ms, slow 240ms, new `--ui-motion-panel` 300ms and `--ui-motion-exit` 100ms, plus stack, flash, skeleton pulse, drag and drag settle tokens. Under reduced motion or `data-ui-motion="off"` every duration token reads 0ms; `motionMs()` reads a token from computed style
10
+ - `AppLayout wide-layout="web"` starts at a 960px container; at 960–1199px the sidebar starts as the 48px rail (was 64px). The sidebar moves its own width on the panel token instead of animating the grid columns. `PageHeader` and `PageToolbar` are one 48px row in the web presentation
11
+ - `AppLayout` takes an `aside` slot with `v-model:aside` (`open`, `collapsed`, `expanded`) and `v-model:aside-width` (380px, 320–560px). New `AsidePanel` fills it: a 48px rail, a docked panel, a floating panel when the page would be narrower than 480px, and a bottom sheet on a phone. `useAsidePreference` stores its state and width
12
+ - New `RecordPanel`: a non-modal record panel docked over the view, so opening, closing and resizing never change the view's width; 560px default, a sash to resize, an optional comments column, a full-screen sheet at 640px and narrower
13
+ - New `AdaptivePanel`: a popover in a wide host and a bottom sheet at 640px and narrower, keeping the draft and focus across the switch
14
+ - Popover, DropdownMenu, Select and the combobox selects share one layer stack: Escape closes only the topmost surface, and an Escape that ends an IME composition closes nothing. `provideOverlayMotion('none')` makes popups inside a grid editor appear at once
15
+ - Skeletons take the final geometry (`SectionSkeleton variant="grid" | "cards" | "fields"`); shapes show after 300ms. Toasts: success 3s, info and warning 5s, danger stays; `pending()` turns into its result in place. New `StatusSlot` and `useShowAfter`. `ToastProvider` drops its `duration` prop
16
+ - New `VirtualCardGrid`, `CardCover` and `CardField`: a virtual card gallery whose card height comes from `cardHeight()`, whose column count is known before the first card renders, and which holds its columns while a side region moves
17
+ - The interaction core (outside layers, IME guard, focus, pointer gesture, edit session), the drag kit (`createDragKit`, `useDragKit`, auto-scroll) and the motion helpers are exported from the package entry ([UX foundation](docs/ux-foundation.md))
18
+ - New `@synopackageland/ui/grid` entry: `GridHost`, a canvas grid ported from Teable's MIT grid, with cell renderers for every field kind, editing with IME-safe first keys, and a save-status store. Load it lazily
19
+ - Five new accessible labels (Checked, Not checked, Rating, Saving, Not saved) and `Restore {name}`, in all nine locales
20
+ - Phone viewport and keyboard layer: `AppRoot full-page` makes the root a `100dvh` page whose document never scrolls (no overscroll reload) and calls `ensureDeviceViewport()`, which now adds `viewport-fit=cover, interactive-widget=resizes-content` (zoom stays on). Every `AppRoot` publishes `--ui-vvh`, `--ui-vv-top`, `--ui-kb-inset` and `data-ui-keyboard="open"` from the visual viewport (60px threshold, one read per frame) and keeps the focused field visible inside its own scroller. New `useVisualViewport`, `focusWithoutScroll` and `useBackDismiss` (Back closes the top sheet, drawer or pushed page only); `useSoftKeyboard` is exported and confirms the keyboard with the viewport
21
+ - Phone and touch: the touch rules now apply in every app (they were keyed on a theme name nobody set). On a coarse pointer every field, select and editable text is 16px, and small controls get a 44px tap box. A phone (640px and narrower) reads 15px body, 13px secondary text, 44px fields and form buttons, 48px list and menu rows and one 48px header; long words break instead of widening a row; hover styles apply only where hover exists ([Mobile-native UI](docs/mobile-native.md))
22
+ - Third-party notices for the ported Teable and Baserow code are in `LICENSES/ux-foundation.md` and `LICENSES/ux-grid-teable.md`
23
+ - Popover and Tooltip use one floating preset (`floating.ts`): 8px plus safe area and soft keyboard from the edge, `sticky: 'partial'`, `hideWhenDetached`, sizes from Reka's available room instead of `100vw`. The AppRoot portal layer clips so a popup never grows the page. Tooltip `openOnTap` is on by default on coarse pointers, and a real tap (with its click) no longer closes it at once
24
+
3
25
  ## 0.20.3 (2026-11-04)
4
26
 
5
27
  - `DataGrid` and `DataTable` remember column widths and view state per App and `stateKey`, so two Apps with the same key no longer share widths; widths saved under the previous key are still read
@@ -0,0 +1,83 @@
1
+ # @synopackageland/ui UX foundation: third-party notices
2
+
3
+ `dist/index.js` contains small ports of MIT-licensed code from Teable and
4
+ Baserow in the interaction core, drag kit, panels and virtual cards. Each
5
+ ported source file keeps the notice below in its header; the built file drops
6
+ those comments and starts with a one-line notice pointing here instead. The
7
+ canvas grid in `dist/grid.js` has its own notices in
8
+ [ux-grid-teable.md](ux-grid-teable.md) and [ux-grid-baserow.md](ux-grid-baserow.md).
9
+
10
+ Nothing is taken from Teable `apps/*` (AGPL-3.0), Baserow `premium/` or
11
+ `enterprise/` (proprietary) or NocoDB (Sustainable Use License); where those
12
+ projects informed a behaviour, only the technique was used. No Teable or
13
+ Baserow name, logo or icon asset is shipped.
14
+
15
+ ## Ported files
16
+
17
+ | Source file in this package | Ported from | Upstream commit |
18
+ | --- | --- | --- |
19
+ | `src/interaction/ime.ts` (`isPrintableKey`) | Teable `packages/sdk/src/components/grid/utils/hotkey.ts` | `f8be01fad` |
20
+ | `src/interaction/gesture.ts` (5px threshold, half-item drop rule) | Teable `packages/sdk/src/components/grid/hooks/useDrag.ts:8-119` | `f8be01fad` |
21
+ | `src/components/primitives/popover/overlay.ts` (`skipAutoFocusOnTouch`) | Teable `packages/ui-lib/src/shadcn/ui/popover.tsx:30-45` | `f8be01fad` |
22
+ | `src/components/composite/record-panel/recordPanelWidth.ts` (width rule) | Teable `packages/sdk/src/components/expand-record/Panel.tsx:20-26, 83-88` | `f8be01fad` |
23
+ | `src/components/composite/record-panel/RecordPanel.vue` (sash, clip layer, drag-to-width) | Teable `packages/sdk/src/components/expand-record/Panel.tsx:100-171`, `packages/ui-lib/src/base/resize-handle/ResizeHandleBar.tsx:1-35` | `f8be01fad` |
24
+ | `src/interaction/outside.ts` (outside-press snapshot and ignore list) | Baserow `web-frontend/modules/core/utils/dom.js` `onClickOutside` | `98f727dc2` |
25
+ | `src/dnd/dragKit.ts` (buffered-rows drag and drop, 100ms swap lock) | Baserow `web-frontend/modules/database/mixins/bufferedRowsDragAndDrop.js:64-235`, `store/view/bufferedRows.js` | `98f727dc2` |
26
+ | `src/dnd/autoScroll.ts` (edge zone and speed ramp) | Baserow `web-frontend/modules/core/directives/autoScroll.js:30-99` | `98f727dc2` |
27
+ | `src/virtual/cardHeight.ts` (`cardHeight`) | Baserow `web-frontend/modules/database/utils/card.js:1-24` | `aa2402b7c716c3eadc5a382af3e880756e026d9c` |
28
+
29
+ ## Teable licence
30
+
31
+ Teable `packages/*` is MIT licensed.
32
+
33
+ ```text
34
+ MIT License
35
+
36
+ Copyright (c) 2023-2025 Teable, Inc.
37
+
38
+ Permission is hereby granted, free of charge, to any person obtaining a copy
39
+ of this software and associated documentation files (the "Software"), to deal
40
+ in the Software without restriction, including without limitation the rights
41
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
42
+ copies of the Software, and to permit persons to whom the Software is
43
+ furnished to do so, subject to the following conditions:
44
+
45
+ The above copyright notice and this permission notice shall be included in all
46
+ copies or substantial portions of the Software.
47
+
48
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
49
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
50
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
51
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
52
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
53
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
54
+ SOFTWARE.
55
+ ```
56
+
57
+ ## Baserow licence
58
+
59
+ Baserow Open Source Edition (outside `premium/` and `enterprise/`) is MIT
60
+ (Expat) licensed.
61
+
62
+ ```text
63
+ MIT License
64
+
65
+ Copyright (c) 2019-present Baserow B.V.
66
+
67
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
68
+ software and associated documentation files (the "Software"), to deal in the Software
69
+ without restriction, including without limitation the rights to use, copy, modify,
70
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
71
+ permit persons to whom the Software is furnished to do so, subject to the following
72
+ conditions:
73
+
74
+ The above copyright notice and this permission notice shall be included in all copies
75
+ or substantial portions of the Software.
76
+
77
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
78
+ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
79
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
80
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
81
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
82
+ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
83
+ ```
@@ -0,0 +1,35 @@
1
+ # @synopackageland/ui/grid: Baserow notice
2
+
3
+ `dist/grid.js` (source `src/grid/clipboard/write.ts`, `writeClipboardAsync`)
4
+ contains a TypeScript port of `copySelectionToClipboard` and
5
+ `writeToClipboard` from Baserow's
6
+ `web-frontend/modules/database/mixins/copyPasteHelper.js:147-218` (commit
7
+ `98f727dc2ed8140fe44e3e797eedb05339562659`). The HTML-table rule in
8
+ `src/grid/clipboard/tsv.ts` (`toHtmlTable`: no table for a single cell) follows
9
+ `prepareHTMLData` in the same file. Baserow licenses all client-side
10
+ JavaScript, including that file, under the MIT (Expat) licence below. Nothing
11
+ from Baserow's `premium/` or `enterprise/` directories is included, and no
12
+ Baserow name, logo or other asset is shipped.
13
+
14
+ ## Baserow licence
15
+
16
+ ```text
17
+ Copyright (c) 2019-present Baserow B.V.
18
+
19
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
20
+ software and associated documentation files (the "Software"), to deal in the Software
21
+ without restriction, including without limitation the rights to use, copy, modify,
22
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
23
+ permit persons to whom the Software is furnished to do so, subject to the following
24
+ conditions:
25
+
26
+ The above copyright notice and this permission notice shall be included in all copies
27
+ or substantial portions of the Software.
28
+
29
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
30
+ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
31
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
32
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
33
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
34
+ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
+ ```
@@ -0,0 +1,48 @@
1
+ # @synopackageland/ui/grid: third-party notice
2
+
3
+ `dist/grid.js` (source `src/grid/` and `src/grid-core/`) contains a TypeScript
4
+ port, without React, of the canvas grid in Teable's SDK package
5
+ (`packages/sdk/src/components/grid/`, commit
6
+ `f8be01fadb86790d3d3a878bedd10cf949f9a8f8`, 2026-11-03). That package is MIT
7
+ licensed (`packages/sdk/LICENSE` and `"license": "MIT"` in
8
+ `packages/sdk/package.json` at that commit). Nothing from Teable's `apps/*`
9
+ (AGPL-3.0) is included, and no Teable name, logo or icon asset is shipped.
10
+
11
+ The Vue host in `src/grid/host/` is new code that follows the coordinate set-up
12
+ in `Grid.tsx` and the pointer flow of `InteractionLayer.tsx`; it calls the
13
+ ported modules and copies no React code. Default theme colours that fill
14
+ missing tokens are Tailwind CSS palette values (MIT, Copyright (c) Tailwind
15
+ Labs, Inc.), as Teable uses them.
16
+
17
+ The fill-handle gesture in `src/grid/host/controller.ts` and `src/grid/range/`
18
+ follows the fill flow of `InteractionLayer.tsx` (preview over the target rows,
19
+ selection grows on release). The fill value rules, the clipboard TSV
20
+ parser/writer and the paste proposal are new code; Teable's fill and
21
+ copy/paste rules live in AGPL `apps/*` code and were not copied. The async
22
+ clipboard write is ported from Baserow (MIT); see `ux-grid-baserow.md`.
23
+
24
+ ## Teable licence
25
+
26
+ ```text
27
+ MIT License
28
+
29
+ Copyright (c) 2023-2025 Teable, Inc.
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining a copy
32
+ of this software and associated documentation files (the "Software"), to deal
33
+ in the Software without restriction, including without limitation the rights
34
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
+ copies of the Software, and to permit persons to whom the Software is
36
+ furnished to do so, subject to the following conditions:
37
+
38
+ The above copyright notice and this permission notice shall be included in all
39
+ copies or substantial portions of the Software.
40
+
41
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
44
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
47
+ SOFTWARE.
48
+ ```
package/README.md CHANGED
@@ -547,6 +547,9 @@ DSM-style application building blocks:
547
547
  - FacetPanel (filter groups with counts; a bottom sheet on a phone) / TagEditor (tags edited in place, saved optimistically)
548
548
  - SplitPane / StorageMeter / StackedBar (see [docs/size-and-split.md](docs/size-and-split.md))
549
549
  - ListDetail (a list with the selected item's detail beside it, the pane's width set by dragging and remembered; see [docs/list-detail.md](docs/list-detail.md))
550
+ - AsidePanel (the right side region: rail, docked, floating, sheet) / RecordPanel (a non-modal record panel docked over the view) / AdaptivePanel (a popover on desktop, a bottom sheet on a phone) / StatusSlot
551
+ - VirtualCardGrid / CardCover / CardField (a virtual card gallery whose card height is computed, never measured)
552
+ - Interaction core, drag kit and motion helpers for app views (see [docs/ux-foundation.md](docs/ux-foundation.md); phone and touch rules in [docs/mobile-native.md](docs/mobile-native.md)); the canvas grid is the separate `@synopackageland/ui/grid` entry
550
553
 
551
554
  `Tabs` and `SectionTabs` move a raised selection notch in 120ms. Selected labels
552
555
  are blue; main labels are bold 14px and section labels bold 13px. `Tabs` fades its
package/dist/cli.js CHANGED
File without changes
@@ -1,10 +1,10 @@
1
- import { AppNavigation, WideLayout } from '../../../lib/adaptiveLayout';
1
+ import { AppAsideState, AppNavigation, WideLayout } from '../../../lib/adaptiveLayout';
2
2
  type __VLS_Props = {
3
3
  sidebarWidth?: string;
4
4
  minHeight?: string;
5
5
  /** Disable responsive layout if an application deliberately manages it itself. */
6
6
  responsive?: boolean;
7
- /** `web` opts a full-page Portal into the full-page layout at 1200px or wider; DSM windows keep `window`. */
7
+ /** `web` opts a full-page Portal into the full-page layout at 960px or wider (the sidebar starts as the rail below 1200); DSM windows keep `window`. */
8
8
  wideLayout?: WideLayout;
9
9
  /** Remembers the web sidebar's width and collapse under `${key}:app-sidebar`; use an app-unique key. */
10
10
  sidebarStorageKey?: string;
@@ -34,11 +34,38 @@ type __VLS_Slots = {
34
34
  footer?: () => unknown;
35
35
  /** A phone's bottom tab bar (AppTabBar), shown only in the mobile presentation. */
36
36
  tabbar?: () => unknown;
37
+ /**
38
+ * The right side region. `overlay` is true when the open aside floats over
39
+ * the page (the page would be narrower than 480px, or the layout is not
40
+ * `web`); on a phone the region has no width and its content places itself.
41
+ */
42
+ aside?: (props: {
43
+ state: AppAsideState;
44
+ overlay: boolean;
45
+ width: number;
46
+ presentation: 'mobile' | 'window' | 'web';
47
+ }) => unknown;
48
+ };
49
+ type __VLS_ModelProps = {
50
+ /**
51
+ * The `aside` slot's state: `open` beside the page, `collapsed` to the 48px
52
+ * rail, or `expanded` over the whole content area (the sidebar stays). The
53
+ * slot's content (an AsidePanel) draws the panel and the rail; the layout
54
+ * only sizes the region and moves it.
55
+ */
56
+ 'aside'?: AppAsideState;
57
+ /** The open aside's width in px, kept within 320-560; the handle on its start edge writes it. */
58
+ 'asideWidth'?: number;
37
59
  };
38
- declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
60
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
61
+ declare const __VLS_base: import('vue').DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
39
62
  brand: (event: MouseEvent) => any;
40
- }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
63
+ "update:aside": (value: AppAsideState) => any;
64
+ "update:asideWidth": (value: number) => any;
65
+ }, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
41
66
  onBrand?: ((event: MouseEvent) => any) | undefined;
67
+ "onUpdate:aside"?: ((value: AppAsideState) => any) | undefined;
68
+ "onUpdate:asideWidth"?: ((value: number) => any) | undefined;
42
69
  }>, {
43
70
  height: "auto" | "fill";
44
71
  minHeight: string;
@@ -25,6 +25,14 @@ type __VLS_Props = {
25
25
  * then DSM's language in a DSM window, then the browser's.
26
26
  */
27
27
  locale?: UiLocale;
28
+ /**
29
+ * The app owns the whole page (a Portal or standalone launch, never a DSM
30
+ * desktop window). The root becomes the page: `100dvh` tall, the document
31
+ * under it never scrolls and has no overscroll reload, and the page gets a
32
+ * device-width, safe-area and keyboard-resizing viewport
33
+ * (`ensureDeviceViewport`). Fixed for the mounted root.
34
+ */
35
+ fullPage?: boolean;
28
36
  };
29
37
  declare var __VLS_7: {}, __VLS_9: {};
30
38
  type __VLS_Slots = {} & {
@@ -40,6 +48,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {},
40
48
  modalScope: "document" | "app";
41
49
  dialogBounds: "app" | "viewport";
42
50
  colorScheme: "light" | "dark";
51
+ fullPage: boolean;
43
52
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
44
53
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
45
54
  declare const _default: typeof __VLS_export;
@@ -0,0 +1,69 @@
1
+ import { Component } from 'vue';
2
+ import { AppAsideState } from '../../../lib/adaptiveLayout';
3
+ type __VLS_Props = {
4
+ /** The panel's title and accessible name, already translated (e.g. the assistant's name). */
5
+ title: string;
6
+ /** The rail and phone button's icon. */
7
+ icon?: Component;
8
+ /** A 6px dot on the rail and the phone button. */
9
+ unread?: boolean;
10
+ /** The phone button that opens the sheet; without it the app opens the sheet itself. */
11
+ fab?: boolean;
12
+ /** Offers `expanded` (the panel takes the content area). */
13
+ expandable?: boolean;
14
+ /** Where focus goes when the panel opens: `field` (the first field in the composer or body, not on touch), the `panel`, or `none`. */
15
+ initialFocus?: 'field' | 'panel' | 'none';
16
+ /** Shown after the rail button's name in its tooltip, e.g. `Ctrl+J`. The app binds the key. */
17
+ shortcut?: string;
18
+ openLabel?: string;
19
+ collapseLabel?: string;
20
+ expandLabel?: string;
21
+ restoreLabel?: string;
22
+ };
23
+ type SlotProps = {
24
+ state: AppAsideState;
25
+ mode: Mode;
26
+ collapse: () => void;
27
+ expand: () => void;
28
+ restore: () => void;
29
+ };
30
+ type __VLS_Slots = {
31
+ /** Surface tabs above the header row (a SegmentControl size="sm"); shown only when given. */
32
+ tabs?: (props: SlotProps) => unknown;
33
+ /** Extra header actions before expand and collapse (a ⋯ menu). */
34
+ actions?: (props: SlotProps) => unknown;
35
+ /** The thread: it scrolls, and its scroll position survives every state. */
36
+ default?: (props: SlotProps) => unknown;
37
+ /** The composer, kept at the bottom; its draft survives every state. */
38
+ composer?: (props: SlotProps) => unknown;
39
+ };
40
+ type Mode = 'docked' | 'floating' | 'sheet';
41
+ declare function open(): void;
42
+ declare function collapse(): void;
43
+ declare function expand(): void;
44
+ declare function restore(): void;
45
+ declare function toggle(): void;
46
+ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
47
+ open: typeof open;
48
+ collapse: typeof collapse;
49
+ expand: typeof expand;
50
+ restore: typeof restore;
51
+ toggle: typeof toggle;
52
+ state: import('vue').WritableComputedRef<AppAsideState, AppAsideState>;
53
+ mode: import('vue').ComputedRef<Mode>;
54
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
55
+ initialFocus: "field" | "panel" | "none";
56
+ shortcut: string;
57
+ icon: Component;
58
+ expandable: boolean;
59
+ unread: boolean;
60
+ fab: boolean;
61
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
62
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
63
+ declare const _default: typeof __VLS_export;
64
+ export default _default;
65
+ type __VLS_WithSlots<T, S> = T & {
66
+ new (): {
67
+ $slots: S;
68
+ };
69
+ };
@@ -0,0 +1,28 @@
1
+ import { Ref } from 'vue';
2
+ import { AppAsideState } from '../../../lib/adaptiveLayout';
3
+ /**
4
+ * One stored entry per scope (a page kind the app names, such as `editor` or
5
+ * `shell`) under one localStorage key:
6
+ * `{"v":1,"editor":{"state":"open","width":380},"shell":{"state":"collapsed","width":380}}`.
7
+ * Other fields an app keeps in a scope's entry (a selected tab) are left as they are.
8
+ * The library knows no routes: the app picks the scope for the page it shows.
9
+ */
10
+ export type AsidePreference = {
11
+ state: AppAsideState;
12
+ width: number;
13
+ };
14
+ export declare function clampAsideWidth(width: number): number;
15
+ /** The stored state and width for `scope`, or the defaults. Synchronous, so a first paint can use it. */
16
+ export declare function readAsidePreference(key: string, scope: string, defaults?: Partial<AsidePreference>): AsidePreference;
17
+ export declare function writeAsidePreference(key: string, scope: string, value: Partial<AsidePreference>): void;
18
+ /**
19
+ * The aside's state and width for AppLayout's `v-model:aside` and
20
+ * `v-model:aside-width`, read during setup (no second paint) and written on
21
+ * every change. AppLayout changes the width only when a drag ends or a key
22
+ * moves the handle, so the width is written once per resize. Another tab's
23
+ * change is picked up on the next page load, never live.
24
+ */
25
+ export declare function useAsidePreference(key: string, scope: string, defaults?: Partial<AsidePreference>): {
26
+ state: Ref<AppAsideState>;
27
+ width: Ref<number>;
28
+ };
@@ -0,0 +1,61 @@
1
+ import { OverlayMotion } from '../../primitives/popover/overlay';
2
+ type __VLS_Props = {
3
+ /** Controlled open state (`v-model:open`). */
4
+ open?: boolean;
5
+ /** Names the panel: the sheet's title, and the popover's accessible name. */
6
+ title?: string;
7
+ /** A line under the sheet's title. */
8
+ description?: string;
9
+ /** The popover's place beside the trigger. */
10
+ side?: 'top' | 'right' | 'bottom' | 'left';
11
+ align?: 'start' | 'center' | 'end';
12
+ /** The popover's width. */
13
+ width?: string;
14
+ /** The edge the sheet comes from. */
15
+ sheetSide?: 'bottom' | 'right';
16
+ /** The sheet's height (bottom) or width (right). */
17
+ sheetSize?: string;
18
+ /** At this host width and narrower the panel is a sheet. */
19
+ compactBelow?: number;
20
+ /** The element whose width decides; defaults to the enclosing AppRoot, else the document. */
21
+ container?: HTMLElement | null;
22
+ /** The sheet's close button label; the Sheet's localized default otherwise. */
23
+ closeLabel?: string;
24
+ /** Popover motion; `none` inside a grid editor. */
25
+ motion?: OverlayMotion;
26
+ };
27
+ declare var __VLS_11: {}, __VLS_23: {
28
+ compact: boolean;
29
+ }, __VLS_31: {
30
+ compact: boolean;
31
+ };
32
+ type __VLS_Slots = {} & {
33
+ trigger?: (props: typeof __VLS_11) => any;
34
+ } & {
35
+ footer?: (props: typeof __VLS_23) => any;
36
+ } & {
37
+ default?: (props: typeof __VLS_31) => any;
38
+ };
39
+ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
40
+ "update:open": (value: boolean) => any;
41
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
42
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
43
+ }>, {
44
+ width: string;
45
+ side: "top" | "right" | "bottom" | "left";
46
+ align: "start" | "center" | "end";
47
+ open: boolean;
48
+ motion: OverlayMotion;
49
+ sheetSide: "bottom" | "right";
50
+ sheetSize: string;
51
+ compactBelow: number;
52
+ container: HTMLElement | null;
53
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
54
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
55
+ declare const _default: typeof __VLS_export;
56
+ export default _default;
57
+ type __VLS_WithSlots<T, S> = T & {
58
+ new (): {
59
+ $slots: S;
60
+ };
61
+ };
@@ -39,9 +39,9 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {},
39
39
  "onSelect-lane"?: ((id: string) => any) | undefined;
40
40
  }>, {
41
41
  compact: boolean;
42
+ cards: boolean;
42
43
  selectable: boolean;
43
44
  selectedLane: string | number;
44
- cards: boolean;
45
45
  layout: "stacked" | "columns";
46
46
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
47
47
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -39,8 +39,8 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {},
39
39
  variant: "dropzone" | "compact";
40
40
  disabled: boolean;
41
41
  modelValue: File[];
42
- multiple: boolean;
43
42
  paste: boolean;
43
+ multiple: boolean;
44
44
  maxFiles: number;
45
45
  maxSize: number;
46
46
  directory: boolean;
@@ -15,12 +15,12 @@ type __VLS_Props = {
15
15
  boundary?: HTMLElement;
16
16
  };
17
17
  declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
18
- choose: (person: MentionCandidate) => any;
19
18
  close: () => any;
19
+ choose: (person: MentionCandidate) => any;
20
20
  hover: (index: number) => any;
21
21
  }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
22
- onChoose?: ((person: MentionCandidate) => any) | undefined;
23
22
  onClose?: (() => any) | undefined;
23
+ onChoose?: ((person: MentionCandidate) => any) | undefined;
24
24
  onHover?: ((index: number) => any) | undefined;
25
25
  }>, {
26
26
  loading: boolean;
@@ -9,7 +9,7 @@ type __VLS_Props = {
9
9
  };
10
10
  declare var __VLS_1: {}, __VLS_4: string, __VLS_5: {
11
11
  item: OverflowToolbarItem;
12
- }, __VLS_35: {}, __VLS_37: {}, __VLS_124: {
12
+ }, __VLS_35: {}, __VLS_37: {}, __VLS_126: {
13
13
  item: OverflowToolbarItem;
14
14
  };
15
15
  type __VLS_Slots = {} & {
@@ -21,7 +21,7 @@ type __VLS_Slots = {} & {
21
21
  } & {
22
22
  right?: (props: typeof __VLS_37) => any;
23
23
  } & {
24
- 'overflow-item'?: (props: typeof __VLS_124) => any;
24
+ 'overflow-item'?: (props: typeof __VLS_126) => any;
25
25
  };
26
26
  declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
27
27
  clickItem: (item: OverflowToolbarMenuEntry | OverflowToolbarItem) => any;
@@ -0,0 +1,77 @@
1
+ export type RecordPanelCloseReason = 'escape' | 'button' | 'swipe';
2
+ type __VLS_Props = {
3
+ /** Controlled open state (`v-model:open`). */
4
+ open?: boolean;
5
+ /** The panel's accessible name (the record's title, or "Record"), already translated. */
6
+ label?: string;
7
+ /** The main column's width (`v-model:width`); the stored or default width otherwise. */
8
+ width?: number;
9
+ /** Remembers the dragged width in localStorage under this key (one per App). */
10
+ storageKey?: string;
11
+ defaultWidth?: number;
12
+ minWidth?: number;
13
+ /** The view kept visible beside the panel, however wide it is dragged. */
14
+ minMainWidth?: number;
15
+ /** Shows the `secondary` slot (comments) as a column on the far side; the panel grows by `secondaryWidth`. */
16
+ secondaryOpen?: boolean;
17
+ secondaryWidth?: number;
18
+ /** The element the panel docks to and is clipped by; it must be positioned. The parent element otherwise. */
19
+ container?: HTMLElement | null;
20
+ /** At this host width and narrower the panel is a full-screen sheet. */
21
+ compactBelow?: number;
22
+ /** Where focus goes on close when the element that had it at open is gone (a re-rendered card). */
23
+ returnFocus?: () => HTMLElement | null | undefined;
24
+ /** `field`: the first editable field (not on touch); `panel`: the panel itself; `none`: focus stays. */
25
+ initialFocus?: 'field' | 'panel' | 'none';
26
+ /** No body padding; the caller lays the body out. */
27
+ flush?: boolean;
28
+ closeLabel?: string;
29
+ resizeLabel?: string;
30
+ };
31
+ type __VLS_Slots = {
32
+ header?: (props: SlotProps) => unknown;
33
+ default?: (props: SlotProps) => unknown;
34
+ secondary?: (props: SlotProps) => unknown;
35
+ };
36
+ type SlotProps = {
37
+ compact: boolean;
38
+ width: number;
39
+ padding: number;
40
+ close: () => void;
41
+ };
42
+ declare function close(reason?: RecordPanelCloseReason): void;
43
+ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
44
+ close: typeof close;
45
+ compact: import('vue').ComputedRef<boolean>;
46
+ width: import('vue').ComputedRef<number>;
47
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
48
+ close: (reason: RecordPanelCloseReason) => any;
49
+ "update:open": (value: boolean) => any;
50
+ "update:width": (value: number) => any;
51
+ resizeEnd: (value: number) => any;
52
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
53
+ onClose?: ((reason: RecordPanelCloseReason) => any) | undefined;
54
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
55
+ "onUpdate:width"?: ((value: number) => any) | undefined;
56
+ onResizeEnd?: ((value: number) => any) | undefined;
57
+ }>, {
58
+ width: number;
59
+ open: boolean;
60
+ minWidth: number;
61
+ compactBelow: number;
62
+ container: HTMLElement | null;
63
+ defaultWidth: number;
64
+ minMainWidth: number;
65
+ secondaryOpen: boolean;
66
+ secondaryWidth: number;
67
+ returnFocus: () => HTMLElement | null | undefined;
68
+ initialFocus: "field" | "panel" | "none";
69
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
70
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
71
+ declare const _default: typeof __VLS_export;
72
+ export default _default;
73
+ type __VLS_WithSlots<T, S> = T & {
74
+ new (): {
75
+ $slots: S;
76
+ };
77
+ };
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @license MIT
3
+ * The width rule (560 default, 320 minimum, 240 of the view kept beside the
4
+ * panel, the secondary column added on top and capped at the host) is ported
5
+ * from Teable's record side panel
6
+ * (packages/sdk/src/components/expand-record/Panel.tsx:20-26, 83-88 at
7
+ * f8be01fad).
8
+ *
9
+ * Copyright (c) 2023-2025 Teable, Inc.
10
+ *
11
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ * of this software and associated documentation files (the "Software"), to deal
13
+ * in the Software without restriction, including without limitation the rights
14
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ * copies of the Software, and to permit persons to whom the Software is
16
+ * furnished to do so, subject to the following conditions:
17
+ *
18
+ * The above copyright notice and this permission notice shall be included in all
19
+ * copies or substantial portions of the Software.
20
+ *
21
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ * SOFTWARE.
28
+ */
29
+ export declare const RECORD_PANEL_DEFAULT_WIDTH = 560;
30
+ export declare const RECORD_PANEL_MIN_WIDTH = 320;
31
+ /** However wide the panel is dragged, this much of the view stays visible beside it. */
32
+ export declare const RECORD_PANEL_MIN_MAIN_WIDTH = 240;
33
+ /** The comments (or other secondary) column, added on the panel's far side. */
34
+ export declare const RECORD_PANEL_SECONDARY_WIDTH = 320;
35
+ /** Body padding switches from 24 to 48 at this body width (Teable `getBodyPadding`). */
36
+ export declare const RECORD_PANEL_WIDE_BODY = 640;
37
+ export interface RecordPanelBounds {
38
+ minWidth: number;
39
+ minMainWidth: number;
40
+ }
41
+ /** The widest the main column may be in a host; unbounded while the host is not measured. */
42
+ export declare function maxPanelWidth(hostWidth: number, bounds: RecordPanelBounds): number;
43
+ /** The main column's width: the stored width clamped to the host. */
44
+ export declare function clampPanelWidth(width: number, hostWidth: number, bounds: RecordPanelBounds): number;
45
+ /**
46
+ * True when the host cannot hold a docked panel with the view beside it, or is
47
+ * phone-narrow: the panel becomes a full-screen sheet. An unmeasured host
48
+ * (zero) stays docked.
49
+ */
50
+ export declare function panelNeedsSheet(hostWidth: number, compactBelow: number, bounds: RecordPanelBounds): boolean;
51
+ /** 24 px below a 640 px body, 48 px from there. */
52
+ export declare function bodyPadding(bodyWidth: number): number;
53
+ export declare function readStoredWidth(key: string | undefined): number | undefined;
54
+ export declare function writeStoredWidth(key: string | undefined, width: number): void;