@leavepulse/ui 0.74.2 → 0.76.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +44 -0
  2. package/dist/assets/{LpShortcutsDialog-BUp_BX4s.css → LpShortcutsDialog-C6uzPeMf.css} +7 -7
  3. package/dist/assets/{LpTable-DHvorDiU.css → LpTable-Bv-EcQs7.css} +19 -19
  4. package/dist/assets/LpTabs-CJ0rYQbx.css +18 -0
  5. package/dist/chunks/{LpAddressInput-Al3HT5ey.js → LpAddressInput-De_LTYM7.js} +1 -1
  6. package/dist/chunks/{LpAppShell-CpSSm5WT.js → LpAppShell-Cpy_t1U_.js} +1 -1
  7. package/dist/chunks/{LpConfirmDialog-DY2VjDji.js → LpConfirmDialog-CphJR6Q9.js} +4 -2
  8. package/dist/chunks/{LpConfirmHost-DvSZTJ4N.js → LpConfirmHost-QSJ0zl63.js} +1 -1
  9. package/dist/chunks/{LpDrawer-RRamxbLV.js → LpDrawer-DQZixOqJ.js} +13 -0
  10. package/dist/chunks/{LpModal-BnjZ2iem.js → LpModal-C0tGg_D_.js} +13 -0
  11. package/dist/chunks/{LpModalNav-DQpV2kdn.js → LpModalNav-iDDtT9c1.js} +2 -2
  12. package/dist/chunks/{LpSidebar-BoNLKgh-.js → LpSidebar-D6zO8vLm.js} +1 -1
  13. package/dist/components/LpAddressInput.vue.js +1 -1
  14. package/dist/components/LpAppShell.vue.js +1 -1
  15. package/dist/components/LpConfirmDialog.vue.d.ts +4 -0
  16. package/dist/components/LpConfirmDialog.vue.js +1 -1
  17. package/dist/components/LpConfirmHost.vue.js +1 -1
  18. package/dist/components/LpDrawer.vue.d.ts +16 -0
  19. package/dist/components/LpDrawer.vue.js +1 -1
  20. package/dist/components/LpModal.vue.d.ts +9 -0
  21. package/dist/components/LpModal.vue.js +1 -1
  22. package/dist/components/LpModalNav.vue.js +1 -1
  23. package/dist/components/LpShortcutsDialog.vue.d.ts +4 -0
  24. package/dist/components/LpShortcutsDialog.vue.js +6 -4
  25. package/dist/components/LpSidebar.vue.js +1 -1
  26. package/dist/components/LpTable.vue.d.ts +37 -0
  27. package/dist/components/LpTable.vue.js +34 -15
  28. package/dist/components/LpTabs.vue.d.ts +9 -0
  29. package/dist/components/LpTabs.vue.js +18 -4
  30. package/dist/components/tableFilter.d.ts +28 -0
  31. package/dist/components/tableFilter.js +43 -0
  32. package/dist/composables/overlayHistory.d.ts +33 -0
  33. package/dist/composables/overlayHistory.js +237 -0
  34. package/dist/composables/useOverlayHistory.d.ts +45 -0
  35. package/dist/composables/useOverlayHistory.js +84 -0
  36. package/dist/composables/useTableFilterChoice.d.ts +16 -0
  37. package/dist/composables/useTableFilterChoice.js +34 -0
  38. package/dist/index.d.ts +6 -0
  39. package/dist/index.js +18 -8
  40. package/package.json +2 -1
  41. package/src/components/LpConfirmDialog.vue +5 -1
  42. package/src/components/LpDrawer.vue +21 -0
  43. package/src/components/LpModal.vue +21 -1
  44. package/src/components/LpShortcutsDialog.vue +5 -1
  45. package/src/components/LpTable.vue +86 -23
  46. package/src/components/LpTabs.vue +26 -2
  47. package/src/components/tableFilter.ts +66 -0
  48. package/src/composables/overlayHistory.ts +381 -0
  49. package/src/composables/useOverlayHistory.ts +173 -0
  50. package/src/composables/useTableFilterChoice.ts +51 -0
  51. package/src/index.ts +6 -0
  52. package/dist/assets/LpTabs-CDchzoRL.css +0 -18
package/README.md CHANGED
@@ -83,6 +83,50 @@ app.use(lpConfig({
83
83
 
84
84
  A component's own `labels` prop wins over the configuration.
85
85
 
86
+ ### Back and Forward for overlays
87
+
88
+ `provideOverlayHistory()` (at the app root, like `provideGlass()`) makes the
89
+ browser's Back button close overlays instead of leaving the page:
90
+
91
+ ```ts
92
+ import { provideOverlayHistory } from "@leavepulse/ui"
93
+
94
+ // in App.vue's setup; pass the router so a Back that only closes a dialog is not a navigation
95
+ provideOverlayHistory(true, { router })
96
+ ```
97
+
98
+ - Opening an `LpModal` or `LpDrawer` (and what is built on them:
99
+ `LpConfirmDialog`, `LpShortcutsDialog`) adds one history entry. Back closes
100
+ the topmost overlay; nested ones close one per press, top first.
101
+ - Closing through the UI (close button, Escape, the scrim, the app setting
102
+ `open` to false) takes the entry back out, so Back is never spent on a step
103
+ that shows nothing. A `guard` that keeps the overlay open on Back keeps its
104
+ entry too.
105
+ - `LpTabs` inside an open overlay record each switch: Back returns to the
106
+ previous tab before it closes the overlay. Page-level tabs stay out (an app
107
+ keeps those in its URL); `history` on `LpTabs` opts out inside an overlay or
108
+ in on a page without a router.
109
+ - Forward after Back does nothing by default: the step is undone at once, so
110
+ no dead entry is left. The kit only sees a boolean `open`, and what the app
111
+ put into the overlay may be gone by then. `history="reopen"` (or
112
+ `provideOverlayHistory("reopen")`) re-opens it on Forward by emitting
113
+ `update:open` true while the overlay is still mounted.
114
+ - `history` on a single overlay wins over the app-wide mode: `false` keeps an
115
+ overlay out of history, for one the app already opens from its route query
116
+ (it would otherwise take two entries for one dialog).
117
+ - A real navigation (a link, `router.push` to another path) closes the open
118
+ overlays, and the entries they leave under the new page are skipped, so Back
119
+ from it lands on the page in one press. A push that keeps the path (a query
120
+ or hash, such as an overlay driven by the route query) leaves them open.
121
+
122
+ The URL never changes and the router's own `history.state` data is copied into
123
+ each entry. The `router` option is vue-router's instance (anything with a
124
+ `listening` switch works): without it the router sees each Back that closes an
125
+ overlay as a visit to the page it is already on (guards and `afterEach` run
126
+ again, nothing remounts). A Forward onto a kit entry still reaches it that
127
+ way, because the entry it starts from belongs to the router. Plain
128
+ `pushState` and `popstate` only, so WebKit (Safari, WebKitGTK) works too.
129
+
86
130
  ### Nuxt
87
131
 
88
132
  ```ts
@@ -1,12 +1,12 @@
1
1
 
2
2
  /* Two columns where there is room: the list is long enough that one column
3
3
  pushes the last group off a laptop screen. */
4
- .shortcut-groups[data-v-611c415f] {
4
+ .shortcut-groups[data-v-f948ed00] {
5
5
  display: grid;
6
6
  gap: 18px;
7
7
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
8
8
  }
9
- .shortcut-group h3[data-v-611c415f] {
9
+ .shortcut-group h3[data-v-f948ed00] {
10
10
  margin: 0 0 6px;
11
11
  color: var(--color-muted);
12
12
  font-size: 0.7rem;
@@ -14,25 +14,25 @@
14
14
  letter-spacing: 0.06em;
15
15
  text-transform: uppercase;
16
16
  }
17
- .shortcut-group dl[data-v-611c415f] {
17
+ .shortcut-group dl[data-v-f948ed00] {
18
18
  display: flex;
19
19
  flex-direction: column;
20
20
  gap: 1px;
21
21
  margin: 0;
22
22
  }
23
- .shortcut-row[data-v-611c415f] {
23
+ .shortcut-row[data-v-f948ed00] {
24
24
  display: flex;
25
25
  align-items: center;
26
26
  justify-content: space-between;
27
27
  gap: 12px;
28
28
  padding: 5px 0;
29
29
  }
30
- .shortcut-row dt[data-v-611c415f] {
30
+ .shortcut-row dt[data-v-f948ed00] {
31
31
  color: var(--color-ink);
32
32
  font-size: 0.82rem;
33
33
  min-width: 0;
34
34
  }
35
- .shortcut-conflict[data-v-611c415f] {
35
+ .shortcut-conflict[data-v-f948ed00] {
36
36
  display: inline-flex;
37
37
  width: 14px;
38
38
  height: 14px;
@@ -47,7 +47,7 @@
47
47
  vertical-align: middle;
48
48
  cursor: help;
49
49
  }
50
- .shortcut-row dd[data-v-611c415f] {
50
+ .shortcut-row dd[data-v-f948ed00] {
51
51
  display: flex;
52
52
  flex-shrink: 0;
53
53
  gap: 3px;
@@ -11,17 +11,17 @@
11
11
  * fade before closing the gap and the whole list lurches at the end instead of
12
12
  * gliding.
13
13
  */
14
- .lp-row-enter-active[data-v-c1911001],
15
- .lp-row-leave-active[data-v-c1911001] {
14
+ .lp-row-enter-active[data-v-d2bafc29],
15
+ .lp-row-leave-active[data-v-d2bafc29] {
16
16
  transition:
17
17
  opacity var(--duration-fast) var(--ease-emphasized),
18
18
  transform var(--duration-fast) var(--ease-emphasized);
19
19
  }
20
- .lp-row-move[data-v-c1911001] {
20
+ .lp-row-move[data-v-d2bafc29] {
21
21
  transition: transform var(--duration-medium) var(--ease-emphasized);
22
22
  }
23
- .lp-row-enter-from[data-v-c1911001],
24
- .lp-row-leave-to[data-v-c1911001] {
23
+ .lp-row-enter-from[data-v-d2bafc29],
24
+ .lp-row-leave-to[data-v-d2bafc29] {
25
25
  opacity: 0;
26
26
  transform: translateX(-0.5rem);
27
27
  }
@@ -35,7 +35,7 @@
35
35
  * drops out of the table layout entirely. Nothing sits below this row to be
36
36
  * dragged around, so simply not animating its exit costs nothing.
37
37
  */
38
- .lp-row-empty.lp-row-leave-active[data-v-c1911001] {
38
+ .lp-row-empty.lp-row-leave-active[data-v-d2bafc29] {
39
39
  display: none;
40
40
  }
41
41
 
@@ -54,7 +54,7 @@
54
54
  * once anything is selected. An earlier version collapsed the column to nothing
55
55
  * and floated the hover box over the first cell, where it sat on the text.
56
56
  */
57
- .lp-tick[data-v-c1911001] {
57
+ .lp-tick[data-v-d2bafc29] {
58
58
  display: flex;
59
59
  align-items: center;
60
60
  max-width: 0;
@@ -66,17 +66,17 @@
66
66
  padding var(--duration-medium) var(--ease-emphasized),
67
67
  opacity var(--duration-fast) ease;
68
68
  }
69
- .lp-tick-open[data-v-c1911001] {
69
+ .lp-tick-open[data-v-d2bafc29] {
70
70
  max-width: 3.25rem;
71
71
  padding-inline: 1rem;
72
72
  opacity: 1;
73
73
  }
74
- .lp-tick-hidden[data-v-c1911001],
75
- .lp-tick-cue[data-v-c1911001] {
74
+ .lp-tick-hidden[data-v-d2bafc29],
75
+ .lp-tick-cue[data-v-d2bafc29] {
76
76
  opacity: 0;
77
77
  }
78
- tr:hover .lp-tick-cue[data-v-c1911001],
79
- .lp-tick-cue[data-v-c1911001]:focus-within {
78
+ tr:hover .lp-tick-cue[data-v-d2bafc29],
79
+ .lp-tick-cue[data-v-d2bafc29]:focus-within {
80
80
  opacity: 1;
81
81
  }
82
82
 
@@ -84,24 +84,24 @@ tr:hover .lp-tick-cue[data-v-c1911001],
84
84
  turned down the rows change without animating rather than not changing. */
85
85
  /* Only where there is a hover to reveal it; a finger long-presses instead. */
86
86
  @media (hover: none) {
87
- tr:hover .lp-tick-cue[data-v-c1911001] {
87
+ tr:hover .lp-tick-cue[data-v-d2bafc29] {
88
88
  opacity: 0;
89
89
  }
90
90
 
91
91
  /* Nor is there anything for the column's width to hold until then: on a
92
92
  touch screen it stays closed until a long press starts selecting, and
93
93
  eases open like the rest of the column. */
94
- .lp-tick-hidden[data-v-c1911001],
95
- .lp-tick-cue[data-v-c1911001] {
94
+ .lp-tick-hidden[data-v-d2bafc29],
95
+ .lp-tick-cue[data-v-d2bafc29] {
96
96
  max-width: 0;
97
97
  padding-inline: 0;
98
98
  }
99
99
  }
100
100
  @media (prefers-reduced-motion: reduce) {
101
- .lp-row-enter-active[data-v-c1911001],
102
- .lp-row-leave-active[data-v-c1911001],
103
- .lp-row-move[data-v-c1911001],
104
- .lp-tick[data-v-c1911001] {
101
+ .lp-row-enter-active[data-v-d2bafc29],
102
+ .lp-row-leave-active[data-v-d2bafc29],
103
+ .lp-row-move[data-v-d2bafc29],
104
+ .lp-tick[data-v-d2bafc29] {
105
105
  transition: none;
106
106
  }
107
107
  }
@@ -0,0 +1,18 @@
1
+
2
+ .lp-tab-badge-enter-active[data-v-1d673b52],
3
+ .lp-tab-badge-leave-active[data-v-1d673b52] {
4
+ transition:
5
+ opacity var(--duration-fast) var(--ease-emphasized),
6
+ transform var(--duration-fast) var(--ease-emphasized);
7
+ }
8
+ .lp-tab-badge-enter-from[data-v-1d673b52],
9
+ .lp-tab-badge-leave-to[data-v-1d673b52] {
10
+ opacity: 0;
11
+ transform: scale(0.6);
12
+ }
13
+ @media (prefers-reduced-motion: reduce) {
14
+ .lp-tab-badge-enter-active[data-v-1d673b52],
15
+ .lp-tab-badge-leave-active[data-v-1d673b52] {
16
+ transition: none;
17
+ }
18
+ }
@@ -7,7 +7,7 @@ import { _ as _sfc_main$3 } from "./LpButton-CFb44IjC.js";
7
7
  import { _ as _sfc_main$1 } from "./LpFormField-Ch69Jd-X.js";
8
8
  import { _ as _sfc_main$4 } from "./LpIcon--5WSb3jJ.js";
9
9
  import { _ as _sfc_main$5 } from "./LpInput-Tw-yxT4I.js";
10
- import { _ as _sfc_main$7 } from "./LpModal-BnjZ2iem.js";
10
+ import { _ as _sfc_main$7 } from "./LpModal-C0tGg_D_.js";
11
11
  import { _ as _sfc_main$6 } from "./LpSelect-Cxq4yBGd.js";
12
12
  import { useFieldControl } from "../composables/useField.js";
13
13
  import { useLabels } from "../composables/useLpConfig.js";
@@ -7,7 +7,7 @@ import { _ as _sfc_main$3 } from "./LpButton-CFb44IjC.js";
7
7
  import { _ as _sfc_main$4 } from "./LpIcon--5WSb3jJ.js";
8
8
  import { _ as _sfc_main$6 } from "./LpScrollArea-Hz3-JWUG.js";
9
9
  import { _ as _sfc_main$5 } from "./LpShift-CCq7dofl.js";
10
- import { _ as _sfc_main$1 } from "./LpSidebar-BoNLKgh-.js";
10
+ import { _ as _sfc_main$1 } from "./LpSidebar-D6zO8vLm.js";
11
11
  import { useMergedAttrs, mergeClass } from "../composables/useMergedClass.js";
12
12
  const _hoisted_1 = ["href"];
13
13
  const _hoisted_2 = { class: "flex min-w-0 flex-1 flex-col" };
@@ -2,7 +2,7 @@ import { defineComponent, computed, ref, watch, openBlock, createBlock, createSl
2
2
  import { useLabels } from "../composables/useLpConfig.js";
3
3
  import { _ as _sfc_main$2 } from "./LpButton-CFb44IjC.js";
4
4
  import { _ as _sfc_main$3 } from "./LpIcon--5WSb3jJ.js";
5
- import { _ as _sfc_main$1 } from "./LpModal-BnjZ2iem.js";
5
+ import { _ as _sfc_main$1 } from "./LpModal-C0tGg_D_.js";
6
6
  const _hoisted_1 = { class: "inline-flex items-center gap-2.5" };
7
7
  const _hoisted_2 = {
8
8
  key: 0,
@@ -23,6 +23,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
23
23
  loadingLabel: {},
24
24
  action: {},
25
25
  glass: { type: Boolean, default: void 0 },
26
+ history: { type: [Boolean, String], default: void 0 },
26
27
  labels: {}
27
28
  },
28
29
  emits: ["update:open", "confirm", "cancel"],
@@ -76,6 +77,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
76
77
  return (_ctx, _cache) => {
77
78
  return openBlock(), createBlock(_sfc_main$1, {
78
79
  glass: __props.glass,
80
+ history: __props.history,
79
81
  open: __props.open,
80
82
  title: __props.title,
81
83
  description: __props.description,
@@ -130,7 +132,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
130
132
  ]),
131
133
  key: "0"
132
134
  } : void 0
133
- ]), 1032, ["glass", "open", "title", "description"]);
135
+ ]), 1032, ["glass", "history", "open", "title", "description"]);
134
136
  };
135
137
  }
136
138
  });
@@ -1,6 +1,6 @@
1
1
  import { defineComponent, computed, ref, watch, openBlock, createBlock, createCommentVNode } from "vue";
2
2
  import { confirmQueue, settleConfirm } from "../components/confirm.js";
3
- import { _ as _sfc_main$1 } from "./LpConfirmDialog-DY2VjDji.js";
3
+ import { _ as _sfc_main$1 } from "./LpConfirmDialog-CphJR6Q9.js";
4
4
  const _sfc_main = /* @__PURE__ */ defineComponent({
5
5
  __name: "LpConfirmHost",
6
6
  props: {
@@ -4,6 +4,7 @@ import { CLOSE_ICON } from "../components/dropdown.js";
4
4
  import { prefersReducedMotion } from "../composables/easing.js";
5
5
  import { useCloseGuard } from "../composables/useCloseGuard.js";
6
6
  import { useGlass } from "../composables/useGlass.js";
7
+ import { useOverlayHistory } from "../composables/useOverlayHistory.js";
7
8
  import { useLabels } from "../composables/useLpConfig.js";
8
9
  import { usePersisted } from "../composables/usePersisted.js";
9
10
  import { _ as _sfc_main$1 } from "./LpIcon--5WSb3jJ.js";
@@ -48,6 +49,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
48
49
  guard: { type: [Boolean, Function] },
49
50
  glass: { type: Boolean, default: void 0 },
50
51
  ariaLabel: {},
52
+ history: { type: [Boolean, String], default: void 0 },
51
53
  labels: {}
52
54
  },
53
55
  emits: ["update:open"],
@@ -87,6 +89,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
87
89
  if (await allowClose()) emit("update:open", false);
88
90
  }
89
91
  __expose({ close: requestClose });
92
+ useOverlayHistory({
93
+ mode: () => props.history,
94
+ open: () => !!props.open,
95
+ close: async () => {
96
+ if (!await allowClose()) return false;
97
+ emit("update:open", false);
98
+ return true;
99
+ },
100
+ reopen: () => emit("update:open", true),
101
+ navigated: () => emit("update:open", false)
102
+ });
90
103
  function guardClose(event) {
91
104
  if (!armed()) return;
92
105
  event.preventDefault();
@@ -2,6 +2,7 @@ import { defineComponent, ref, computed, useSlots, watch, onBeforeUnmount, openB
2
2
  import { DialogRoot, DialogPortal, DialogOverlay, DialogContent, DialogTitle, DialogDescription, DialogClose } from "reka-ui";
3
3
  import { useCloseGuard } from "../composables/useCloseGuard.js";
4
4
  import { useGlass } from "../composables/useGlass.js";
5
+ import { useOverlayHistory } from "../composables/useOverlayHistory.js";
5
6
  import { useLabels } from "../composables/useLpConfig.js";
6
7
  import { useShift } from "../composables/useShift.js";
7
8
  import { useModalLayer } from "../components/modalDepth.js";
@@ -47,6 +48,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
47
48
  role: {},
48
49
  dismissible: { type: Boolean, default: true },
49
50
  guard: { type: [Boolean, Function], default: void 0 },
51
+ history: { type: [Boolean, String], default: void 0 },
50
52
  labels: {}
51
53
  },
52
54
  emits: ["update:open"],
@@ -64,6 +66,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
64
66
  function close() {
65
67
  void onOpenChange(false);
66
68
  }
69
+ useOverlayHistory({
70
+ mode: () => props.history,
71
+ open: () => !!props.open,
72
+ close: async () => {
73
+ if (!await allowClose()) return false;
74
+ emit("update:open", false);
75
+ return true;
76
+ },
77
+ reopen: () => emit("update:open", true),
78
+ navigated: () => emit("update:open", false)
79
+ });
67
80
  __expose({ close });
68
81
  function onEscape(event) {
69
82
  guardOutside(event);
@@ -3,8 +3,8 @@ import { useGlass } from "../composables/useGlass.js";
3
3
  import { useLabels } from "../composables/useLpConfig.js";
4
4
  import { _ as _sfc_main$2 } from "./LpButton-CFb44IjC.js";
5
5
  import { _ as _sfc_main$3 } from "./LpIcon--5WSb3jJ.js";
6
- import { _ as _sfc_main$1 } from "./LpModal-BnjZ2iem.js";
7
- import { _ as _sfc_main$4 } from "./LpSidebar-BoNLKgh-.js";
6
+ import { _ as _sfc_main$1 } from "./LpModal-C0tGg_D_.js";
7
+ import { _ as _sfc_main$4 } from "./LpSidebar-D6zO8vLm.js";
8
8
  const _hoisted_1 = { class: "flex items-center gap-2" };
9
9
  const _sfc_main = /* @__PURE__ */ defineComponent({
10
10
  __name: "LpModalNav",
@@ -2,7 +2,7 @@ import { defineComponent, computed, ref, useId, openBlock, createElementBlock, F
2
2
  import { useHotkeys, parseCombo } from "../composables/useHotkeys.js";
3
3
  import { usePersisted } from "../composables/usePersisted.js";
4
4
  import { useLabels } from "../composables/useLpConfig.js";
5
- import { _ as _sfc_main$5 } from "./LpDrawer-RRamxbLV.js";
5
+ import { _ as _sfc_main$5 } from "./LpDrawer-DQZixOqJ.js";
6
6
  import { _ as _sfc_main$2 } from "./LpIcon--5WSb3jJ.js";
7
7
  import { _ as _sfc_main$3 } from "./LpInput-Tw-yxT4I.js";
8
8
  import { _ as _sfc_main$1 } from "./LpTooltip-BcBvIx4z.js";
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpAddressInput-Al3HT5ey.js";
1
+ import { _ as _sfc_main } from "../chunks/LpAddressInput-De_LTYM7.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpAppShell-CpSSm5WT.js";
1
+ import { _ as _sfc_main } from "../chunks/LpAppShell-Cpy_t1U_.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,3 +1,4 @@
1
+ import type { OverlayHistoryMode } from "../composables/useOverlayHistory";
1
2
  export type ConfirmLabels = {
2
3
  confirm: string;
3
4
  cancel: string;
@@ -44,6 +45,8 @@ type __VLS_Props = {
44
45
  action?: () => unknown;
45
46
  /** Frosted glass panel, passed to LpModal. Follows `provideGlass` when unset. */
46
47
  glass?: boolean;
48
+ /** Browser history for the dialog, passed to LpModal. Follows `provideOverlayHistory` when unset. */
49
+ history?: OverlayHistoryMode;
47
50
  labels?: Partial<ConfirmLabels>;
48
51
  };
49
52
  declare var __VLS_16: {};
@@ -59,6 +62,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
59
62
  "onUpdate:open"?: ((value: boolean) => any) | undefined;
60
63
  onConfirm?: (() => any) | undefined;
61
64
  }>, {
65
+ history: OverlayHistoryMode;
62
66
  glass: boolean;
63
67
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
64
68
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpConfirmDialog-DY2VjDji.js";
1
+ import { _ as _sfc_main } from "../chunks/LpConfirmDialog-CphJR6Q9.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpConfirmHost-DvSZTJ4N.js";
1
+ import { _ as _sfc_main } from "../chunks/LpConfirmHost-QSJ0zl63.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,5 @@
1
1
  import { type CloseGuard } from "../composables/useCloseGuard";
2
+ import { type OverlayHistoryMode } from "../composables/useOverlayHistory";
2
3
  declare const _default: typeof __VLS_export;
3
4
  export default _default;
4
5
  declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
@@ -86,6 +87,13 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
86
87
  glass?: boolean;
87
88
  /** Accessible name for a drawer without a visible `title`. */
88
89
  ariaLabel?: string;
90
+ /**
91
+ * Browser Back closes it, and opening it adds a history entry. Unset
92
+ * follows `provideOverlayHistory` (off without one); `"reopen"` also
93
+ * opens it again on Forward; `false` keeps it out of history, for an
94
+ * overlay the app already drives from its route.
95
+ */
96
+ history?: OverlayHistoryMode;
89
97
  labels?: Partial<{
90
98
  close: string;
91
99
  }>;
@@ -178,12 +186,20 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
178
186
  glass?: boolean;
179
187
  /** Accessible name for a drawer without a visible `title`. */
180
188
  ariaLabel?: string;
189
+ /**
190
+ * Browser Back closes it, and opening it adds a history entry. Unset
191
+ * follows `provideOverlayHistory` (off without one); `"reopen"` also
192
+ * opens it again on Forward; `false` keeps it out of history, for an
193
+ * overlay the app already drives from its route.
194
+ */
195
+ history?: OverlayHistoryMode;
181
196
  labels?: Partial<{
182
197
  close: string;
183
198
  }>;
184
199
  }> & Readonly<{
185
200
  "onUpdate:open"?: ((value: boolean) => any) | undefined;
186
201
  }>, {
202
+ history: OverlayHistoryMode;
187
203
  size: "sm" | "md" | "lg" | "xl";
188
204
  side: "left" | "right";
189
205
  glass: boolean;
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpDrawer-RRamxbLV.js";
1
+ import { _ as _sfc_main } from "../chunks/LpDrawer-DQZixOqJ.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,5 @@
1
1
  import { type CloseGuard } from "../composables/useCloseGuard";
2
+ import { type OverlayHistoryMode } from "../composables/useOverlayHistory";
2
3
  type __VLS_Props = {
3
4
  open?: boolean;
4
5
  title?: string;
@@ -52,6 +53,13 @@ type __VLS_Props = {
52
53
  * form's state, `:guard="form.dirty"`. See `useCloseGuard`.
53
54
  */
54
55
  guard?: CloseGuard;
56
+ /**
57
+ * Browser Back closes it, and opening it adds a history entry. Unset
58
+ * follows `provideOverlayHistory` (off without one); `"reopen"` also
59
+ * opens it again on Forward; `false` keeps it out of history, for an
60
+ * overlay the app already drives from its route.
61
+ */
62
+ history?: OverlayHistoryMode;
55
63
  labels?: Partial<{
56
64
  close: string;
57
65
  }>;
@@ -91,6 +99,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
91
99
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
92
100
  "onUpdate:open"?: ((value: boolean) => any) | undefined;
93
101
  }>, {
102
+ history: OverlayHistoryMode;
94
103
  size: "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "full";
95
104
  autoFocus: "auto" | "none" | string;
96
105
  glass: boolean;
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpModal-BnjZ2iem.js";
1
+ import { _ as _sfc_main } from "../chunks/LpModal-C0tGg_D_.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpModalNav-DQpV2kdn.js";
1
+ import { _ as _sfc_main } from "../chunks/LpModalNav-iDDtT9c1.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,3 +1,4 @@
1
+ import type { OverlayHistoryMode } from "../composables/useOverlayHistory";
1
2
  import { type ShortcutGroup } from "../composables/useHotkeys";
2
3
  type __VLS_Props = {
3
4
  open?: boolean;
@@ -8,6 +9,8 @@ type __VLS_Props = {
8
9
  description?: string;
9
10
  /** Frosted glass panel, passed to LpModal. Follows `provideGlass` when unset. */
10
11
  glass?: boolean;
12
+ /** Browser history for the dialog, passed to LpModal. Follows `provideOverlayHistory` when unset. */
13
+ history?: OverlayHistoryMode;
11
14
  /**
12
15
  * A key that toggles the reference, e.g. "F1". Bound only while the dialog
13
16
  * is mounted, also inside inputs and over other overlays, and the browser's
@@ -20,6 +23,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
20
23
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
21
24
  "onUpdate:open"?: ((value: boolean) => any) | undefined;
22
25
  }>, {
26
+ history: OverlayHistoryMode;
23
27
  title: string;
24
28
  open: boolean;
25
29
  glass: boolean;
@@ -1,10 +1,10 @@
1
1
  import { defineComponent, computed, openBlock, createBlock, unref, withCtx, createElementVNode, createElementBlock, Fragment, renderList, toDisplayString, createTextVNode, createCommentVNode, createVNode } from "vue";
2
2
  import LpKeys from "./LpKeys.vue.js";
3
- import { _ as _sfc_main$1 } from "../chunks/LpModal-BnjZ2iem.js";
3
+ import { _ as _sfc_main$1 } from "../chunks/LpModal-C0tGg_D_.js";
4
4
  import { mergeShortcutGroups, activeShortcuts, useHotkeys } from "../composables/useHotkeys.js";
5
5
  import { useLabels } from "../composables/useLpConfig.js";
6
6
  import { _ as _export_sfc } from "../chunks/_plugin-vue_export-helper-1tPrXgE0.js";
7
- import '../assets/LpShortcutsDialog-BUp_BX4s.css';const _hoisted_1 = { class: "shortcut-groups" };
7
+ import '../assets/LpShortcutsDialog-C6uzPeMf.css';const _hoisted_1 = { class: "shortcut-groups" };
8
8
  const _hoisted_2 = ["aria-label", "title"];
9
9
  const _sfc_main = /* @__PURE__ */ defineComponent({
10
10
  __name: "LpShortcutsDialog",
@@ -15,6 +15,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
15
15
  title: { default: void 0 },
16
16
  description: {},
17
17
  glass: { type: Boolean, default: void 0 },
18
+ history: { type: [Boolean, String], default: void 0 },
18
19
  hotkey: {}
19
20
  },
20
21
  emits: ["update:open"],
@@ -42,6 +43,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
42
43
  return (_ctx, _cache) => {
43
44
  return openBlock(), createBlock(_sfc_main$1, {
44
45
  glass: props.glass,
46
+ history: props.history,
45
47
  open: props.open,
46
48
  size: "lg",
47
49
  title: props.title ?? unref(text).title,
@@ -85,11 +87,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
85
87
  ])
86
88
  ]),
87
89
  _: 1
88
- }, 8, ["glass", "open", "title", "description"]);
90
+ }, 8, ["glass", "history", "open", "title", "description"]);
89
91
  };
90
92
  }
91
93
  });
92
- const LpShortcutsDialog = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-611c415f"]]);
94
+ const LpShortcutsDialog = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-f948ed00"]]);
93
95
  export {
94
96
  LpShortcutsDialog as default
95
97
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpSidebar-BoNLKgh-.js";
1
+ import { _ as _sfc_main } from "../chunks/LpSidebar-D6zO8vLm.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,5 @@
1
1
  import { type CsvOptions } from "./exportData";
2
+ import { type TableFilters } from "./tableFilter";
2
3
  import { type TableRowMenuResult } from "./tableRowMenu";
3
4
  export interface TableColumn<Row> {
4
5
  key: string;
@@ -29,6 +30,21 @@ export interface TableColumn<Row> {
29
30
  * vocabulary; the menu should say what the column itself says.
30
31
  */
31
32
  valueLabel?: (value: unknown) => string;
33
+ /**
34
+ * The column's whole vocabulary, when it is known apart from the rows. The
35
+ * funnel lists these first and then anything else the rows hold, so a value
36
+ * is offered even while nothing on the page has it: the rows may already be
37
+ * narrowed by the same column upstream (a control above the table, a server
38
+ * query), and a funnel built only from what arrived could not widen it again.
39
+ */
40
+ filterValues?: readonly unknown[];
41
+ /**
42
+ * Show how many rows hold each value in the funnel (the default). Turn off
43
+ * when the rows are already narrowed by this column before they reach the
44
+ * table: the counts would then claim that the values filtered out upstream
45
+ * hold no rows at all.
46
+ */
47
+ filterCounts?: boolean;
32
48
  /** The value a CSV export writes for this column; the raw cell by default. */
33
49
  exportValue?: (row: Row) => unknown;
34
50
  /** Keep this column out of the show/hide list — an actions column has no
@@ -171,6 +187,23 @@ declare const __VLS_export: <T extends Record<string, unknown>>(__VLS_props: Non
171
187
  /** Active sort (v-model:sort). When set, the parent owns ordering (server
172
188
  * side); otherwise the table sorts its own rows client-side. */
173
189
  sort?: SortState | null;
190
+ /**
191
+ * The header filters (v-model:filters): per column key, the values hidden.
192
+ * When set, the parent owns them, so a control above the table that
193
+ * filters the same column (see `useTableFilterChoice`) and the column's
194
+ * funnel are one state: each shows what the other picked, and the table's
195
+ * resets clear both. Left unset, the table keeps them itself. With
196
+ * `persist`, remembered filters fill only the columns the parent leaves
197
+ * unfiltered, and arrive through `update:filters`.
198
+ */
199
+ filters?: TableFilters;
200
+ /**
201
+ * The rows are narrowed by filters outside the table (a search, a period).
202
+ * An empty table then says nothing matches rather than that there is
203
+ * nothing at all, and its reset button also emits `resetFilters`, for the
204
+ * parent to clear its own.
205
+ */
206
+ filtered?: boolean;
174
207
  /** Pin the header while the body scrolls. Pair with a height on the wrapper. */
175
208
  stickyHeader?: boolean;
176
209
  /** Per-row right-click menu. Return [] (or omit the prop) to disable it for
@@ -213,7 +246,9 @@ declare const __VLS_export: <T extends Record<string, unknown>>(__VLS_props: Non
213
246
  allMatching?: boolean;
214
247
  } & {
215
248
  "onUpdate:selected"?: ((value: (string | number)[]) => any) | undefined;
249
+ onResetFilters?: (() => any) | undefined;
216
250
  "onUpdate:sort"?: ((value: SortState | null) => any) | undefined;
251
+ "onUpdate:filters"?: ((value: TableFilters) => any) | undefined;
217
252
  "onUpdate:allMatching"?: ((value: boolean) => any) | undefined;
218
253
  onRowClick?: ((row: T) => any) | undefined;
219
254
  }> & (typeof globalThis extends {
@@ -240,6 +275,8 @@ declare const __VLS_export: <T extends Record<string, unknown>>(__VLS_props: Non
240
275
  emit: {
241
276
  (e: "update:selected", value: (string | number)[]): void;
242
277
  (e: "update:sort", value: SortState | null): void;
278
+ (e: "update:filters", value: TableFilters): void;
279
+ (e: "resetFilters"): void;
243
280
  (e: "update:allMatching", value: boolean): void;
244
281
  (e: "rowClick", row: T): void;
245
282
  };