rei-kit 2.23.0 → 2.25.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/dist/tokens.css CHANGED
@@ -22,7 +22,7 @@
22
22
  --color-surface: #ffffff;
23
23
  --color-muted: #ddf4e7;
24
24
  --color-ink: #0f2229;
25
- --color-ink-soft: #5c7480;
25
+ --color-ink-soft: #586f7b;
26
26
  --color-hair: #e1edea;
27
27
 
28
28
  /* ---------------------------------------------------------------------
@@ -72,7 +72,7 @@
72
72
  --color-primary: #26667f;
73
73
  --color-accent: #124170;
74
74
  --color-positive: #67c090;
75
- --color-negative: #c9463b;
75
+ --color-negative: #c7453a;
76
76
  --color-warning: #d89a3e;
77
77
 
78
78
  --color-on-primary: #ffffff;
@@ -87,7 +87,7 @@
87
87
  --color-primary: #26667f;
88
88
  --color-accent: #124170;
89
89
  --color-positive: #67c090;
90
- --color-negative: #c9463b;
90
+ --color-negative: #c7453a;
91
91
  --color-warning: #d89a3e;
92
92
 
93
93
  --color-on-primary: #ffffff;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * What the keyboard can reach, as one selector.
3
+ *
4
+ * Three parts of the kit ask this question and each had written its own
5
+ * answer, which is how three answers came to differ: the dialog trap and
6
+ * the popover agreed, and `ScrollArea` left out `:not([disabled])`, so a
7
+ * box holding nothing but disabled buttons counted as reachable and was
8
+ * denied the focus stop that would have been its only way in.
9
+ *
10
+ * `summary` belongs here for the same reason it belonged in `ScrollArea`:
11
+ * a `<details>` heading takes focus, and a dialog whose trap skipped one
12
+ * would let Tab out of itself.
13
+ *
14
+ * Two things it deliberately does not do. It does not check whether an
15
+ * element is visible or inside an `inert` subtree — a selector cannot, and
16
+ * every caller here is already scoped to something on screen. And it is
17
+ * not what a roving-tabindex container should use to find its own
18
+ * controls: `[tabindex]:not([tabindex="-1"])` matches exactly the one
19
+ * control such a container has already put in the tab order, so it would
20
+ * find one item and then stop. `BaseToolbar` says so where it keeps its
21
+ * own.
22
+ */
23
+ export declare const FOCUSABLE = "a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), summary, [tabindex]:not([tabindex=\"-1\"])";
24
+ /** The reachable elements inside `root`, in document order. */
25
+ export declare function focusableWithin(root: Element | null | undefined): HTMLElement[];
@@ -43,6 +43,7 @@ type __VLS_Props = {
43
43
  openDelay?: number | undefined;
44
44
  /** How long it survives the pointer leaving, so the card can be reached. */
45
45
  closeDelay?: number | undefined;
46
+ /** Which side it prefers. It opens on the other when there is more room there. */
46
47
  placement?: 'top' | 'bottom' | undefined;
47
48
  };
48
49
  type __VLS_Slots = {
@@ -15,6 +15,7 @@
15
15
  */
16
16
  export { default as BaseAccordion } from './BaseAccordion.vue';
17
17
  export type { AccordionItem } from './BaseAccordion.vue';
18
+ /** Where this page sits, and the way back up. */
18
19
  export { default as BaseBreadcrumb } from './BaseBreadcrumb.vue';
19
20
  export type { Crumb } from './BaseBreadcrumb.vue';
20
21
  /**
@@ -29,6 +30,7 @@ export type { Crumb } from './BaseBreadcrumb.vue';
29
30
  * Menu key, or it is a set of actions a keyboard cannot reach at all.
30
31
  */
31
32
  export { default as BaseContextMenu } from './BaseContextMenu.vue';
33
+ /** One section that opens and closes. */
32
34
  export { default as BaseDisclosure } from './BaseDisclosure.vue';
33
35
  /**
34
36
  * `BaseHoverCard`, for when the answer is a thing rather than a sentence —
@@ -48,6 +50,7 @@ export { default as BaseDrawer } from './BaseDrawer.vue';
48
50
  * to make somebody reaching for one notice the other exists.
49
51
  */
50
52
  export { default as BaseModal } from './BaseModal.vue';
53
+ /** Moving between pages of a list. */
51
54
  export { default as BasePagination } from './BasePagination.vue';
52
55
  /**
53
56
  * Everything the app can do, behind ⌘K. In the wide entry because it is a
@@ -67,9 +70,18 @@ export type { DataColumn, TableSort } from './DataTable.vue';
67
70
  * a desk-sized screen is arranged with, and that a phone never shows.
68
71
  */
69
72
  export { default as BaseSplitter } from './BaseSplitter.vue';
73
+ /**
74
+ * A row of controls that belong together: a formatting bar, a row of view
75
+ * switches, the actions over a table.
76
+ */
70
77
  export { default as BaseToolbar } from './BaseToolbar.vue';
78
+ /**
79
+ * A tree of things that contain things: folders, a category list, a table
80
+ * of contents.
81
+ */
71
82
  export { default as BaseTree } from './BaseTree.vue';
72
83
  export type { TreeNode } from './BaseTree.vue';
84
+ /** Two lists and the way between them: what is available, what is chosen. */
73
85
  export { default as TransferList } from './TransferList.vue';
74
86
  /**
75
87
  * One question, asked the way the screen expects: a modal on a wide screen,
@@ -77,11 +89,18 @@ export { default as TransferList } from './TransferList.vue';
77
89
  * app that only ever shows the sheet should reach for `BaseSheet` itself.
78
90
  */
79
91
  export { default as ResponsiveDialog } from './ResponsiveDialog.vue';
92
+ /** Sections of one page, one visible at a time. */
80
93
  export { default as BaseTabs } from './BaseTabs.vue';
81
94
  export type { TabPanel } from './BaseTabs.vue';
95
+ /** A short label that appears beside a control. */
82
96
  export { default as BaseTooltip } from './BaseTooltip.vue';
97
+ /**
98
+ * A wide site's navigation, where a section has more in it than a row can
99
+ * hold: columns of links under a heading, opened from the bar.
100
+ */
83
101
  export { default as MegaMenu } from './MegaMenu.vue';
84
102
  export type { MegaMenuColumn, MegaMenuItem, MegaMenuLink } from './MegaMenu.vue';
103
+ /** The primary navigation of a wide site. */
85
104
  export { default as NavLinks } from './NavLinks.vue';
86
105
  export type { NavLinkItem } from './NavLinks.vue';
87
106
  /**
package/dist/web.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as BaseCheckbox_default, c as useBoundValue, d as ensureSheetRoot, n as elementDirection, o as BaseSheet_default, r as horizontalStep, s as inertOutside, t as focusTarget } from "./focus-target-DRgd8UnQ.js";
2
- import { a as useMediaQuery, i as useMenuKeys, n as ScrollArea_default, r as BaseSkeleton_default, t as BaseListbox_default } from "./BaseListbox-BrIZxUmx.js";
2
+ import { a as BaseSkeleton_default, c as useMediaQuery, i as focusableWithin, n as ScrollArea_default, o as useMenuKeys, s as useAnchoredPanel, t as BaseListbox_default } from "./BaseListbox-DvZ7IhNn.js";
3
3
  import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BOaGB7Aw.js";
4
4
  import { t as BaseButton_default } from "./BaseButton-RN2an975.js";
5
5
  import { Fragment, Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, mergeModels, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, shallowRef, toDisplayString, unref, useId, useModel, useTemplateRef, vModelText, vShow, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
@@ -310,6 +310,14 @@ var BaseHoverCard_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
310
310
  setup(__props) {
311
311
  const id = useId();
312
312
  const open = ref(false);
313
+ const root = ref(null);
314
+ const panel = ref(null);
315
+ const { placed, shift } = useAnchoredPanel({
316
+ root,
317
+ panel,
318
+ open,
319
+ side: __props.placement
320
+ });
313
321
  let timer;
314
322
  function clear() {
315
323
  if (timer !== void 0) clearTimeout(timer);
@@ -349,6 +357,8 @@ var BaseHoverCard_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
349
357
  onBeforeUnmount(clear);
350
358
  return (_ctx, _cache) => {
351
359
  return openBlock(), createElementBlock("div", {
360
+ ref_key: "root",
361
+ ref: root,
352
362
  class: "rk-hovercard",
353
363
  onPointerenter: show,
354
364
  onPointerleave: hide,
@@ -358,37 +368,22 @@ var BaseHoverCard_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
358
368
  }, [renderSlot(_ctx.$slots, "default", { props: triggerProps.value }, void 0, true), open.value ? (openBlock(), createElementBlock("div", {
359
369
  key: 0,
360
370
  id: unref(id),
361
- class: normalizeClass(["rk-hovercard-panel surface-raised", `is-${__props.placement}`]),
371
+ ref_key: "panel",
372
+ ref: panel,
373
+ class: normalizeClass(["rk-hovercard-panel surface-raised", `is-${unref(placed)}`]),
374
+ style: normalizeStyle(unref(shift) ? { "--rk-hovercard-shift": `${unref(shift)}px` } : void 0),
362
375
  role: "group",
363
376
  "aria-label": __props.label
364
- }, [renderSlot(_ctx.$slots, "card", {}, void 0, true)], 10, _hoisted_1$15)) : createCommentVNode("", true)], 32);
377
+ }, [renderSlot(_ctx.$slots, "card", {}, void 0, true)], 14, _hoisted_1$15)) : createCommentVNode("", true)], 544);
365
378
  };
366
379
  }
367
- }), [["__scopeId", "data-v-70c09916"]]);
380
+ }), [["__scopeId", "data-v-d3c3b40f"]]);
368
381
  //#endregion
369
382
  //#region src/composables/use-dialog-shell.ts
370
- /**
371
- * What every modal surface has to do, in one place.
372
- *
373
- * A dialog, a drawer and anything else that takes the whole page share a
374
- * list that is easy to get nearly right: trap Tab, stop Escape, make the
375
- * rest of the page inert, stop it scrolling underneath, and hand focus back
376
- * to whatever opened it. Each of those has an order that matters, and the
377
- * orders are not obvious — releasing `inert` *after* restoring focus drops
378
- * it on the body, because an inert element cannot take focus. That was
379
- * written once, correctly, in `BaseModal`; a drawer that copied it would be
380
- * a second copy to keep correct.
381
- *
382
- * The Tab wrap has to be done by hand: the browser's own Tab order is the
383
- * whole document, and a dialog is only part of it. `inert` is what also
384
- * stops a screen reader's virtual cursor, which walks straight past a
385
- * keydown handler.
386
- */
387
- var FOCUSABLE$1 = "a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
388
383
  function useDialogShell(open, panel, { dismissible = () => true, onClose }) {
389
384
  let releaseInert = null;
390
385
  let restoreTo = null;
391
- const focusable = () => panel.value ? Array.from(panel.value.querySelectorAll(FOCUSABLE$1)) : [];
386
+ const focusable = () => panel.value ? focusableWithin(panel.value) : [];
392
387
  function onKeydown(event) {
393
388
  if (event.key === "Escape" && dismissible()) {
394
389
  event.stopPropagation();
@@ -1271,7 +1266,7 @@ var BaseToolbar_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__
1271
1266
  }, [renderSlot(_ctx.$slots, "default", {}, void 0, true)], 42, _hoisted_1$8);
1272
1267
  };
1273
1268
  }
1274
- }), [["__scopeId", "data-v-d49198bf"]]);
1269
+ }), [["__scopeId", "data-v-ad876ad1"]]);
1275
1270
  //#endregion
1276
1271
  //#region src/web/BaseTree.vue?vue&type=script&setup=true&lang.ts
1277
1272
  var _hoisted_1$7 = ["aria-label", "aria-multiselectable"];