@smwb/ui-react 2.8.0 → 2.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/AI_LESS_OVERRIDES.md +84 -21
- package/AI_THEMING.md +72 -28
- package/README.md +654 -0
- package/dist/assets/styles/less/components/appBar/appBar.entry.css +1 -1
- package/dist/assets/styles/less/components/button/button.entry.css +1 -1
- package/dist/assets/styles/less/components/checkbox/checkbox.entry.css +1 -1
- package/dist/assets/styles/less/components/chip/chip.entry.css +1 -1
- package/dist/assets/styles/less/components/commandPalette/commandPalette.entry.css +1 -0
- package/dist/assets/styles/less/components/composer/composer.entry.css +1 -0
- package/dist/assets/styles/less/components/dagView/dagView.entry.css +1 -0
- package/dist/assets/styles/less/components/diffStat/diffStat.entry.css +1 -0
- package/dist/assets/styles/less/components/kbd/kbd.entry.css +1 -0
- package/dist/assets/styles/less/components/list/list.entry.css +1 -1
- package/dist/assets/styles/less/components/qrCode/qrCode.entry.css +1 -0
- package/dist/assets/styles/less/components/radioButton/radioButton.entry.css +1 -1
- package/dist/assets/styles/less/components/selectField/selectField.entry.css +1 -1
- package/dist/assets/styles/less/components/sidebar/sidebar.entry.css +1 -1
- package/dist/assets/styles/less/components/statusDot/statusDot.entry.css +1 -0
- package/dist/assets/styles/less/components/swimlanes/swimlanes.entry.css +1 -0
- package/dist/assets/styles/less/components/tabGroups/tabGroups.entry.css +1 -0
- package/dist/assets/styles/less/components/tabs/tab/tab.entry.css +1 -1
- package/dist/assets/styles/less/components/tabs/tabPanel/tabPanel.entry.css +1 -0
- package/dist/assets/styles/less/components/tabs/tabs.entry.css +1 -1
- package/dist/assets/styles/less/components/textField/textField.entry.css +1 -1
- package/dist/assets/styles/less/components/toggle/toggle.entry.css +1 -1
- package/dist/assets/styles/less/components/treeView/treeView.entry.css +1 -1
- package/dist/assets/styles/less/tokens.entry.css +1 -1
- package/dist/components/dataDisplay/chat/chat.d.ts +43 -1
- package/dist/components/dataDisplay/chat/chat.js +179 -150
- package/dist/components/dataDisplay/chat/chat.js.map +1 -1
- package/dist/components/dataDisplay/chat/chatComposer.d.ts +17 -0
- package/dist/components/dataDisplay/chat/chatComposer.js +31 -29
- package/dist/components/dataDisplay/chat/chatComposer.js.map +1 -1
- package/dist/components/dataDisplay/chat/index.d.ts +1 -1
- package/dist/components/dataDisplay/chat/utils.d.ts +14 -0
- package/dist/components/dataDisplay/chat/utils.js.map +1 -1
- package/dist/components/dataDisplay/dagView/dagLayout.d.ts +74 -0
- package/dist/components/dataDisplay/dagView/dagLayout.js +289 -0
- package/dist/components/dataDisplay/dagView/dagLayout.js.map +1 -0
- package/dist/components/dataDisplay/dagView/dagView.d.ts +157 -0
- package/dist/components/dataDisplay/dagView/dagView.js +543 -0
- package/dist/components/dataDisplay/dagView/dagView.js.map +1 -0
- package/dist/components/dataDisplay/dagView/index.d.ts +4 -0
- package/dist/components/dataDisplay/dagView/panZoom.d.ts +75 -0
- package/dist/components/dataDisplay/dagView/panZoom.js +171 -0
- package/dist/components/dataDisplay/dagView/panZoom.js.map +1 -0
- package/dist/components/dataDisplay/diffStat/diffStat.d.ts +54 -0
- package/dist/components/dataDisplay/diffStat/diffStat.js +63 -0
- package/dist/components/dataDisplay/diffStat/diffStat.js.map +1 -0
- package/dist/components/dataDisplay/diffStat/index.d.ts +2 -0
- package/dist/components/dataDisplay/kbd/index.d.ts +4 -0
- package/dist/components/dataDisplay/kbd/kbd.d.ts +40 -0
- package/dist/components/dataDisplay/kbd/kbd.js +27 -0
- package/dist/components/dataDisplay/kbd/kbd.js.map +1 -0
- package/dist/components/dataDisplay/kbd/kbdKeys.d.ts +18 -0
- package/dist/components/dataDisplay/kbd/kbdKeys.js +72 -0
- package/dist/components/dataDisplay/kbd/kbdKeys.js.map +1 -0
- package/dist/components/dataDisplay/list/listItem.d.ts +34 -0
- package/dist/components/dataDisplay/list/listItem.js +47 -24
- package/dist/components/dataDisplay/list/listItem.js.map +1 -1
- package/dist/components/dataDisplay/qrCode/index.d.ts +2 -0
- package/dist/components/dataDisplay/qrCode/qrCode.d.ts +28 -0
- package/dist/components/dataDisplay/qrCode/qrCode.js +78 -0
- package/dist/components/dataDisplay/qrCode/qrCode.js.map +1 -0
- package/dist/components/dataDisplay/qrCode/qrCodePath.d.ts +7 -0
- package/dist/components/dataDisplay/qrCode/qrCodePath.js +20 -0
- package/dist/components/dataDisplay/qrCode/qrCodePath.js.map +1 -0
- package/dist/components/dataDisplay/statusDot/index.d.ts +2 -0
- package/dist/components/dataDisplay/statusDot/statusDot.d.ts +35 -0
- package/dist/components/dataDisplay/statusDot/statusDot.js +30 -0
- package/dist/components/dataDisplay/statusDot/statusDot.js.map +1 -0
- package/dist/components/dataDisplay/swimlanes/index.d.ts +2 -0
- package/dist/components/dataDisplay/swimlanes/swimlanes.d.ts +53 -0
- package/dist/components/dataDisplay/swimlanes/swimlanes.js +357 -0
- package/dist/components/dataDisplay/swimlanes/swimlanes.js.map +1 -0
- package/dist/components/dataDisplay/treeView/treeView.d.ts +17 -1
- package/dist/components/dataDisplay/treeView/treeView.js +113 -92
- package/dist/components/dataDisplay/treeView/treeView.js.map +1 -1
- package/dist/components/feedBack/modal/modal.js +84 -63
- package/dist/components/feedBack/modal/modal.js.map +1 -1
- package/dist/components/inputs/button/button.d.ts +13 -1
- package/dist/components/inputs/button/button.js +57 -51
- package/dist/components/inputs/button/button.js.map +1 -1
- package/dist/components/inputs/composer/composer.d.ts +149 -0
- package/dist/components/inputs/composer/composer.js +219 -0
- package/dist/components/inputs/composer/composer.js.map +1 -0
- package/dist/components/inputs/composer/composerFiles.d.ts +26 -0
- package/dist/components/inputs/composer/composerFiles.js +19 -0
- package/dist/components/inputs/composer/composerFiles.js.map +1 -0
- package/dist/components/inputs/composer/composerKeys.d.ts +29 -0
- package/dist/components/inputs/composer/composerKeys.js +7 -0
- package/dist/components/inputs/composer/composerKeys.js.map +1 -0
- package/dist/components/inputs/composer/index.d.ts +3 -0
- package/dist/components/layout/sheet/sheet.d.ts +12 -0
- package/dist/components/layout/sheet/sheet.js +152 -137
- package/dist/components/layout/sheet/sheet.js.map +1 -1
- package/dist/components/layout/tabGroups/index.d.ts +4 -0
- package/dist/components/layout/tabGroups/tabGroups.d.ts +94 -0
- package/dist/components/layout/tabGroups/tabGroups.js +783 -0
- package/dist/components/layout/tabGroups/tabGroups.js.map +1 -0
- package/dist/components/layout/tabGroups/tabGroupsFocus.d.ts +55 -0
- package/dist/components/layout/tabGroups/tabGroupsFocus.js +199 -0
- package/dist/components/layout/tabGroups/tabGroupsFocus.js.map +1 -0
- package/dist/components/layout/tabGroups/tabGroupsLayout.d.ts +250 -0
- package/dist/components/layout/tabGroups/tabGroupsLayout.js +497 -0
- package/dist/components/layout/tabGroups/tabGroupsLayout.js.map +1 -0
- package/dist/components/navigation/appBar/appBar.d.ts +22 -0
- package/dist/components/navigation/appBar/appBar.js +31 -26
- package/dist/components/navigation/appBar/appBar.js.map +1 -1
- package/dist/components/navigation/commandPalette/commandPalette.d.ts +111 -0
- package/dist/components/navigation/commandPalette/commandPalette.js +337 -0
- package/dist/components/navigation/commandPalette/commandPalette.js.map +1 -0
- package/dist/components/navigation/commandPalette/commandPaletteFilter.d.ts +11 -0
- package/dist/components/navigation/commandPalette/commandPaletteFilter.js +16 -0
- package/dist/components/navigation/commandPalette/commandPaletteFilter.js.map +1 -0
- package/dist/components/navigation/commandPalette/commandPaletteNavigation.d.ts +13 -0
- package/dist/components/navigation/commandPalette/commandPaletteNavigation.js +38 -0
- package/dist/components/navigation/commandPalette/commandPaletteNavigation.js.map +1 -0
- package/dist/components/navigation/commandPalette/commandPaletteTypes.d.ts +39 -0
- package/dist/components/navigation/commandPalette/index.d.ts +4 -0
- package/dist/components/navigation/sidebar/sidebar.d.ts +10 -0
- package/dist/components/navigation/sidebar/sidebar.js +61 -59
- package/dist/components/navigation/sidebar/sidebar.js.map +1 -1
- package/dist/components/navigation/tabs/index.d.ts +3 -1
- package/dist/components/navigation/tabs/tab/tab.d.ts +88 -1
- package/dist/components/navigation/tabs/tab/tab.js +121 -42
- package/dist/components/navigation/tabs/tab/tab.js.map +1 -1
- package/dist/components/navigation/tabs/tabPanel/tabPanel.d.ts +19 -0
- package/dist/components/navigation/tabs/tabPanel/tabPanel.js +27 -0
- package/dist/components/navigation/tabs/tabPanel/tabPanel.js.map +1 -0
- package/dist/components/navigation/tabs/tabs.d.ts +75 -5
- package/dist/components/navigation/tabs/tabs.js +369 -145
- package/dist/components/navigation/tabs/tabs.js.map +1 -1
- package/dist/components/navigation/tabs/tabs.utils.d.ts +20 -0
- package/dist/components/navigation/tabs/tabs.utils.js +11 -0
- package/dist/components/navigation/tabs/tabs.utils.js.map +1 -0
- package/dist/components/navigation/tabs/tabsContext.d.ts +11 -0
- package/dist/components/navigation/tabs/tabsContext.js +6 -0
- package/dist/components/navigation/tabs/tabsContext.js.map +1 -0
- package/dist/headless/components/dataDisplay/chat/chat.js +179 -150
- package/dist/headless/components/dataDisplay/chat/chat.js.map +1 -1
- package/dist/headless/components/dataDisplay/chat/chatComposer.js +31 -29
- package/dist/headless/components/dataDisplay/chat/chatComposer.js.map +1 -1
- package/dist/headless/components/dataDisplay/chat/utils.js.map +1 -1
- package/dist/headless/components/dataDisplay/dagView/dagLayout.js +289 -0
- package/dist/headless/components/dataDisplay/dagView/dagLayout.js.map +1 -0
- package/dist/headless/components/dataDisplay/dagView/dagView.js +541 -0
- package/dist/headless/components/dataDisplay/dagView/dagView.js.map +1 -0
- package/dist/headless/components/dataDisplay/dagView/panZoom.js +171 -0
- package/dist/headless/components/dataDisplay/dagView/panZoom.js.map +1 -0
- package/dist/headless/components/dataDisplay/diffStat/diffStat.js +61 -0
- package/dist/headless/components/dataDisplay/diffStat/diffStat.js.map +1 -0
- package/dist/headless/components/dataDisplay/kbd/kbd.js +25 -0
- package/dist/headless/components/dataDisplay/kbd/kbd.js.map +1 -0
- package/dist/headless/components/dataDisplay/kbd/kbdKeys.js +72 -0
- package/dist/headless/components/dataDisplay/kbd/kbdKeys.js.map +1 -0
- package/dist/headless/components/dataDisplay/list/listItem.js +47 -24
- package/dist/headless/components/dataDisplay/list/listItem.js.map +1 -1
- package/dist/headless/components/dataDisplay/qrCode/qrCode.js +76 -0
- package/dist/headless/components/dataDisplay/qrCode/qrCode.js.map +1 -0
- package/dist/headless/components/dataDisplay/qrCode/qrCodePath.js +20 -0
- package/dist/headless/components/dataDisplay/qrCode/qrCodePath.js.map +1 -0
- package/dist/headless/components/dataDisplay/statusDot/statusDot.js +28 -0
- package/dist/headless/components/dataDisplay/statusDot/statusDot.js.map +1 -0
- package/dist/headless/components/dataDisplay/swimlanes/swimlanes.js +355 -0
- package/dist/headless/components/dataDisplay/swimlanes/swimlanes.js.map +1 -0
- package/dist/headless/components/dataDisplay/treeView/treeView.js +113 -92
- package/dist/headless/components/dataDisplay/treeView/treeView.js.map +1 -1
- package/dist/headless/components/feedBack/modal/modal.js +85 -64
- package/dist/headless/components/feedBack/modal/modal.js.map +1 -1
- package/dist/headless/components/inputs/button/button.js +56 -50
- package/dist/headless/components/inputs/button/button.js.map +1 -1
- package/dist/headless/components/inputs/composer/composer.js +217 -0
- package/dist/headless/components/inputs/composer/composer.js.map +1 -0
- package/dist/headless/components/inputs/composer/composerFiles.js +19 -0
- package/dist/headless/components/inputs/composer/composerFiles.js.map +1 -0
- package/dist/headless/components/inputs/composer/composerKeys.js +7 -0
- package/dist/headless/components/inputs/composer/composerKeys.js.map +1 -0
- package/dist/headless/components/layout/sheet/sheet.js +160 -145
- package/dist/headless/components/layout/sheet/sheet.js.map +1 -1
- package/dist/headless/components/layout/tabGroups/tabGroups.js +781 -0
- package/dist/headless/components/layout/tabGroups/tabGroups.js.map +1 -0
- package/dist/headless/components/layout/tabGroups/tabGroupsFocus.js +199 -0
- package/dist/headless/components/layout/tabGroups/tabGroupsFocus.js.map +1 -0
- package/dist/headless/components/layout/tabGroups/tabGroupsLayout.js +497 -0
- package/dist/headless/components/layout/tabGroups/tabGroupsLayout.js.map +1 -0
- package/dist/headless/components/navigation/appBar/appBar.js +35 -30
- package/dist/headless/components/navigation/appBar/appBar.js.map +1 -1
- package/dist/headless/components/navigation/commandPalette/commandPalette.js +335 -0
- package/dist/headless/components/navigation/commandPalette/commandPalette.js.map +1 -0
- package/dist/headless/components/navigation/commandPalette/commandPaletteFilter.js +16 -0
- package/dist/headless/components/navigation/commandPalette/commandPaletteFilter.js.map +1 -0
- package/dist/headless/components/navigation/commandPalette/commandPaletteNavigation.js +38 -0
- package/dist/headless/components/navigation/commandPalette/commandPaletteNavigation.js.map +1 -0
- package/dist/headless/components/navigation/sidebar/sidebar.js +56 -54
- package/dist/headless/components/navigation/sidebar/sidebar.js.map +1 -1
- package/dist/headless/components/navigation/tabs/tab/tab.js +121 -42
- package/dist/headless/components/navigation/tabs/tab/tab.js.map +1 -1
- package/dist/headless/components/navigation/tabs/tabPanel/tabPanel.js +25 -0
- package/dist/headless/components/navigation/tabs/tabPanel/tabPanel.js.map +1 -0
- package/dist/headless/components/navigation/tabs/tabs.js +369 -145
- package/dist/headless/components/navigation/tabs/tabs.js.map +1 -1
- package/dist/headless/components/navigation/tabs/tabs.utils.js +11 -0
- package/dist/headless/components/navigation/tabs/tabs.utils.js.map +1 -0
- package/dist/headless/components/navigation/tabs/tabsContext.js +6 -0
- package/dist/headless/components/navigation/tabs/tabsContext.js.map +1 -0
- package/dist/headless/hooks/useFocusTrap.js +24 -21
- package/dist/headless/hooks/useFocusTrap.js.map +1 -1
- package/dist/headless/hooks/useKeyboardShortcut.js +19 -0
- package/dist/headless/hooks/useKeyboardShortcut.js.map +1 -0
- package/dist/headless/index.js +360 -316
- package/dist/headless/index.js.map +1 -1
- package/dist/headless/utils/keyboardShortcut.js +49 -0
- package/dist/headless/utils/keyboardShortcut.js.map +1 -0
- package/dist/headless/utils/linkAttrs.js +13 -0
- package/dist/headless/utils/linkAttrs.js.map +1 -0
- package/dist/headless/utils/restoreFocus.js +10 -0
- package/dist/headless/utils/restoreFocus.js.map +1 -0
- package/dist/hooks/useFocusTrap.d.ts +6 -1
- package/dist/hooks/useFocusTrap.js +24 -21
- package/dist/hooks/useFocusTrap.js.map +1 -1
- package/dist/hooks/useKeyboardShortcut.d.ts +30 -0
- package/dist/hooks/useKeyboardShortcut.js +19 -0
- package/dist/hooks/useKeyboardShortcut.js.map +1 -0
- package/dist/index.cjs +3 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +24 -3
- package/dist/index.js +360 -316
- package/dist/index.js.map +1 -1
- package/dist/utils/keyboardShortcut.d.ts +12 -0
- package/dist/utils/keyboardShortcut.js +49 -0
- package/dist/utils/keyboardShortcut.js.map +1 -0
- package/dist/utils/linkAttrs.d.ts +13 -0
- package/dist/utils/linkAttrs.js +13 -0
- package/dist/utils/linkAttrs.js.map +1 -0
- package/dist/utils/restoreFocus.d.ts +8 -0
- package/dist/utils/restoreFocus.js +10 -0
- package/dist/utils/restoreFocus.js.map +1 -0
- package/package.json +5 -3
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React, { type HTMLAttributes } from "react";
|
|
2
|
+
import { type KbdPlatform } from "./kbdKeys";
|
|
3
|
+
export interface KbdProps extends Omit<HTMLAttributes<HTMLElement>, "children"> {
|
|
4
|
+
className?: string;
|
|
5
|
+
/**
|
|
6
|
+
* The keys of the shortcut in order, e.g. `["Mod", "K"]` or `["Shift", "Enter"]`. `Mod` is the
|
|
7
|
+
* Command key on macOS and Ctrl elsewhere. On macOS, `Shift`, `Alt`/`Option`, `Ctrl`/`Control`,
|
|
8
|
+
* `Meta`/`Cmd`/`Command`, `Enter`, `Escape`, `Tab`, `Backspace` and `Delete` are drawn as the
|
|
9
|
+
* symbols of the Mac keyboard; elsewhere the same names are drawn as Ctrl, Alt, Shift, Meta, Enter,
|
|
10
|
+
* Esc, Tab, Backspace and Del, whatever their case. `" "` and `Space` are the Space key, `+` and
|
|
11
|
+
* `Plus` the plus key.
|
|
12
|
+
* Arrow names (`ArrowUp` or `Up`, …) are arrows everywhere; any other key is drawn as given
|
|
13
|
+
* (a single letter in upper case).
|
|
14
|
+
*/
|
|
15
|
+
keys: string[];
|
|
16
|
+
/**
|
|
17
|
+
* The platform whose keys are drawn. Without it the browser's own is used: `other` on the
|
|
18
|
+
* server and in the first client render (so that hydration matches), `mac` right after on a Mac.
|
|
19
|
+
* Set it for a fixed look, in stories and in tests.
|
|
20
|
+
*/
|
|
21
|
+
platform?: KbdPlatform;
|
|
22
|
+
/**
|
|
23
|
+
* Drawn between the key caps. By default `+` on `other` and nothing on `mac`, where the symbols
|
|
24
|
+
* stand side by side; `""` draws none. It is for the eye only; assistive technology reads `label`.
|
|
25
|
+
*/
|
|
26
|
+
separator?: string;
|
|
27
|
+
/**
|
|
28
|
+
* What assistive technology reads instead of the key caps. By default the key names, joined
|
|
29
|
+
* with `+` on `other` ("Ctrl+K") and with a space on `mac` ("Command K").
|
|
30
|
+
*/
|
|
31
|
+
label?: string;
|
|
32
|
+
/** Test id of the root `<kbd>`; `kbd` unless given. */
|
|
33
|
+
"data-testid"?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A keyboard shortcut as key caps, for a tooltip, a menu item or a command palette. The root and
|
|
37
|
+
* every cap are `<kbd>`; assistive technology reads one text ("Ctrl+K", "Command K") and skips the caps.
|
|
38
|
+
*/
|
|
39
|
+
export declare const Kbd: React.ForwardRefExoticComponent<KbdProps & React.RefAttributes<HTMLElement>>;
|
|
40
|
+
export default Kbd;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsxs as b, jsx as a } from "react/jsx-runtime";
|
|
2
|
+
import '../../../assets/styles/less/components/kbd/kbd.entry.css';import '../../../assets/styles/less/tokens.entry.css';/* empty css */
|
|
3
|
+
/* empty css */
|
|
4
|
+
import f, { useState as _ } from "react";
|
|
5
|
+
import l from "clsx";
|
|
6
|
+
import { useSafeLayoutEffect as K } from "../../../hooks/useSafeLayoutEffect.js";
|
|
7
|
+
import { kbdKeyLabel as x, detectKbdPlatform as N } from "./kbdKeys.js";
|
|
8
|
+
function j(t) {
|
|
9
|
+
const [s, n] = _("other");
|
|
10
|
+
return K(() => {
|
|
11
|
+
t === void 0 && n(N());
|
|
12
|
+
}, [t]), t != null ? t : s;
|
|
13
|
+
}
|
|
14
|
+
const D = f.forwardRef(function({ className: s, keys: n, platform: u, separator: m, label: c, "data-testid": k = "kbd", ...h }, p) {
|
|
15
|
+
const d = j(u), o = n.map((e) => x(e, d)), r = m != null ? m : d === "mac" ? "" : "+", w = c != null ? c : o.map((e) => e.name).join(d === "mac" ? " " : "+");
|
|
16
|
+
return /* @__PURE__ */ b("kbd", { ...h, ref: p, "data-testid": k, "data-platform": d, className: l("smwb-kbd", s), children: [
|
|
17
|
+
/* @__PURE__ */ a("span", { className: "smwb-kbd__text", children: w }),
|
|
18
|
+
o.map((e, i) => /* @__PURE__ */ b(f.Fragment, { children: [
|
|
19
|
+
i > 0 && r !== "" ? /* @__PURE__ */ a("span", { className: "smwb-kbd__separator", "aria-hidden": "true", children: r }) : null,
|
|
20
|
+
/* @__PURE__ */ a("kbd", { className: "smwb-kbd__key", "aria-hidden": "true", children: e.text })
|
|
21
|
+
] }, i))
|
|
22
|
+
] });
|
|
23
|
+
});
|
|
24
|
+
export {
|
|
25
|
+
D as Kbd
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=kbd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kbd.js","sources":["../../../../src/components/dataDisplay/kbd/kbd.tsx"],"sourcesContent":["import React, { type HTMLAttributes, useState } from \"react\";\nimport cn from \"clsx\";\nimport { useSafeLayoutEffect } from \"../../../hooks/useSafeLayoutEffect\";\nimport { detectKbdPlatform, kbdKeyLabel, type KbdPlatform } from \"./kbdKeys\";\n\nexport interface KbdProps extends Omit<HTMLAttributes<HTMLElement>, \"children\"> {\n className?: string;\n /**\n * The keys of the shortcut in order, e.g. `[\"Mod\", \"K\"]` or `[\"Shift\", \"Enter\"]`. `Mod` is the\n * Command key on macOS and Ctrl elsewhere. On macOS, `Shift`, `Alt`/`Option`, `Ctrl`/`Control`,\n * `Meta`/`Cmd`/`Command`, `Enter`, `Escape`, `Tab`, `Backspace` and `Delete` are drawn as the\n * symbols of the Mac keyboard; elsewhere the same names are drawn as Ctrl, Alt, Shift, Meta, Enter,\n * Esc, Tab, Backspace and Del, whatever their case. `\" \"` and `Space` are the Space key, `+` and\n * `Plus` the plus key.\n * Arrow names (`ArrowUp` or `Up`, …) are arrows everywhere; any other key is drawn as given\n * (a single letter in upper case).\n */\n keys: string[];\n /**\n * The platform whose keys are drawn. Without it the browser's own is used: `other` on the\n * server and in the first client render (so that hydration matches), `mac` right after on a Mac.\n * Set it for a fixed look, in stories and in tests.\n */\n platform?: KbdPlatform;\n /**\n * Drawn between the key caps. By default `+` on `other` and nothing on `mac`, where the symbols\n * stand side by side; `\"\"` draws none. It is for the eye only; assistive technology reads `label`.\n */\n separator?: string;\n /**\n * What assistive technology reads instead of the key caps. By default the key names, joined\n * with `+` on `other` (\"Ctrl+K\") and with a space on `mac` (\"Command K\").\n */\n label?: string;\n /** Test id of the root `<kbd>`; `kbd` unless given. */\n \"data-testid\"?: string;\n}\n\n/** The platform asked for, or the browser's: `other` until the client has mounted. */\nfunction useKbdPlatform(platform: KbdPlatform | undefined): KbdPlatform {\n const [detected, setDetected] = useState<KbdPlatform>(\"other\");\n useSafeLayoutEffect(() => {\n if (platform === undefined) {\n setDetected(detectKbdPlatform());\n }\n }, [platform]);\n return platform ?? detected;\n}\n\n/**\n * A keyboard shortcut as key caps, for a tooltip, a menu item or a command palette. The root and\n * every cap are `<kbd>`; assistive technology reads one text (\"Ctrl+K\", \"Command K\") and skips the caps.\n */\nexport const Kbd = React.forwardRef<HTMLElement, KbdProps>(function Kbd(\n { className, keys, platform: platformProp, separator, label, \"data-testid\": dataTestId = \"kbd\", ...rest },\n ref\n) {\n const platform = useKbdPlatform(platformProp);\n const labels = keys.map((key) => kbdKeyLabel(key, platform));\n const between = separator ?? (platform === \"mac\" ? \"\" : \"+\");\n const spoken = label ?? labels.map((item) => item.name).join(platform === \"mac\" ? \" \" : \"+\");\n\n return (\n <kbd {...rest} ref={ref} data-testid={dataTestId} data-platform={platform} className={cn(\"smwb-kbd\", className)}>\n <span className=\"smwb-kbd__text\">{spoken}</span>\n {labels.map((item, index) => (\n <React.Fragment key={index}>\n {index > 0 && between !== \"\" ? (\n <span className=\"smwb-kbd__separator\" aria-hidden=\"true\">\n {between}\n </span>\n ) : null}\n <kbd className=\"smwb-kbd__key\" aria-hidden=\"true\">\n {item.text}\n </kbd>\n </React.Fragment>\n ))}\n </kbd>\n );\n});\n\nexport default Kbd;\n"],"names":["useKbdPlatform","platform","detected","setDetected","useState","useSafeLayoutEffect","detectKbdPlatform","Kbd","React","className","keys","platformProp","separator","label","dataTestId","rest","ref","labels","key","kbdKeyLabel","between","spoken","item","jsxs","cn","jsx","index"],"mappings":";;;;;;;AAyCA,SAASA,EAAeC,GAAgD;AACtE,QAAM,CAACC,GAAUC,CAAW,IAAIC,EAAsB,OAAO;AAC7D,SAAAC,EAAoB,MAAM;AACxB,IAAIJ,MAAa,UACfE,EAAYG,GAAmB;AAAA,EAEnC,GAAG,CAACL,CAAQ,CAAC,GACNA,KAAA,OAAAA,IAAYC;AACrB;AAMO,MAAMK,IAAMC,EAAM,WAAkC,SACzD,EAAE,WAAAC,GAAW,MAAAC,GAAM,UAAUC,GAAc,WAAAC,GAAW,OAAAC,GAAO,eAAeC,IAAa,OAAO,GAAGC,EAAA,GACnGC,GACA;AACA,QAAMf,IAAWD,EAAeW,CAAY,GACtCM,IAASP,EAAK,IAAI,CAACQ,MAAQC,EAAYD,GAAKjB,CAAQ,CAAC,GACrDmB,IAAUR,KAAA,OAAAA,IAAcX,MAAa,QAAQ,KAAK,KAClDoB,IAASR,KAAA,OAAAA,IAASI,EAAO,IAAI,CAACK,MAASA,EAAK,IAAI,EAAE,KAAKrB,MAAa,QAAQ,MAAM,GAAG;AAE3F,SACE,gBAAAsB,EAAC,OAAA,EAAK,GAAGR,GAAM,KAAAC,GAAU,eAAaF,GAAY,iBAAeb,GAAU,WAAWuB,EAAG,YAAYf,CAAS,GAC5G,UAAA;AAAA,IAAA,gBAAAgB,EAAC,QAAA,EAAK,WAAU,kBAAkB,UAAAJ,GAAO;AAAA,IACxCJ,EAAO,IAAI,CAACK,GAAMI,MACjB,gBAAAH,EAACf,EAAM,UAAN,EACE,UAAA;AAAA,MAAAkB,IAAQ,KAAKN,MAAY,KACxB,gBAAAK,EAAC,QAAA,EAAK,WAAU,uBAAsB,eAAY,QAC/C,UAAAL,EAAA,CACH,IACE;AAAA,wBACH,OAAA,EAAI,WAAU,iBAAgB,eAAY,QACxC,YAAK,KAAA,CACR;AAAA,IAAA,EAAA,GARmBM,CASrB,CACD;AAAA,EAAA,GACH;AAEJ,CAAC;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type KbdPlatform = "mac" | "other";
|
|
2
|
+
/** How one key is drawn, and how it is read out. */
|
|
3
|
+
export interface KbdKeyLabel {
|
|
4
|
+
/** What is drawn on the key cap. */
|
|
5
|
+
text: string;
|
|
6
|
+
/** What assistive technology reads. */
|
|
7
|
+
name: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The platform of the running browser: `mac` for macOS (and iPadOS, which reports itself
|
|
11
|
+
* so), `other` everywhere else and without a `navigator` (on the server).
|
|
12
|
+
*/
|
|
13
|
+
export declare function detectKbdPlatform(): KbdPlatform;
|
|
14
|
+
/**
|
|
15
|
+
* The cap and the spoken name of a key. `Mod` is Command on `mac` and Ctrl on `other`; see the
|
|
16
|
+
* tables above for the rest. A single letter is drawn in upper case; any other key as given.
|
|
17
|
+
*/
|
|
18
|
+
export declare function kbdKeyLabel(key: string, platform: KbdPlatform): KbdKeyLabel;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const n = (e, a) => ({ text: e, name: a }), s = {
|
|
2
|
+
up: n("↑", "Up arrow"),
|
|
3
|
+
arrowup: n("↑", "Up arrow"),
|
|
4
|
+
down: n("↓", "Down arrow"),
|
|
5
|
+
arrowdown: n("↓", "Down arrow"),
|
|
6
|
+
left: n("←", "Left arrow"),
|
|
7
|
+
arrowleft: n("←", "Left arrow"),
|
|
8
|
+
right: n("→", "Right arrow"),
|
|
9
|
+
arrowright: n("→", "Right arrow"),
|
|
10
|
+
// `KeyboardEvent.key` is " " for the space bar, and a bare "+" would read "Ctrl++".
|
|
11
|
+
" ": { text: "Space", name: "Space" },
|
|
12
|
+
space: { text: "Space", name: "Space" },
|
|
13
|
+
spacebar: { text: "Space", name: "Space" },
|
|
14
|
+
"+": { text: "+", name: "Plus" },
|
|
15
|
+
plus: { text: "+", name: "Plus" }
|
|
16
|
+
}, r = { text: "⌘", name: "Command" }, d = {
|
|
17
|
+
mod: r,
|
|
18
|
+
meta: r,
|
|
19
|
+
cmd: r,
|
|
20
|
+
command: r,
|
|
21
|
+
shift: { text: "⇧", name: "Shift" },
|
|
22
|
+
alt: { text: "⌥", name: "Option" },
|
|
23
|
+
option: { text: "⌥", name: "Option" },
|
|
24
|
+
ctrl: { text: "⌃", name: "Control" },
|
|
25
|
+
control: { text: "⌃", name: "Control" },
|
|
26
|
+
enter: { text: "↩", name: "Return" },
|
|
27
|
+
return: { text: "↩", name: "Return" },
|
|
28
|
+
escape: { text: "⎋", name: "Escape" },
|
|
29
|
+
esc: { text: "⎋", name: "Escape" },
|
|
30
|
+
tab: { text: "⇥", name: "Tab" },
|
|
31
|
+
backspace: { text: "⌫", name: "Delete" },
|
|
32
|
+
delete: { text: "⌦", name: "Forward delete" },
|
|
33
|
+
del: { text: "⌦", name: "Forward delete" }
|
|
34
|
+
}, o = { text: "Meta", name: "Meta" }, t = (e, a = e) => ({ text: e, name: a }), i = {
|
|
35
|
+
mod: t("Ctrl"),
|
|
36
|
+
ctrl: t("Ctrl"),
|
|
37
|
+
control: t("Ctrl"),
|
|
38
|
+
alt: t("Alt"),
|
|
39
|
+
option: t("Alt"),
|
|
40
|
+
shift: t("Shift"),
|
|
41
|
+
meta: o,
|
|
42
|
+
cmd: o,
|
|
43
|
+
command: o,
|
|
44
|
+
enter: t("Enter"),
|
|
45
|
+
return: t("Enter"),
|
|
46
|
+
escape: t("Esc", "Escape"),
|
|
47
|
+
esc: t("Esc", "Escape"),
|
|
48
|
+
tab: t("Tab"),
|
|
49
|
+
backspace: t("Backspace"),
|
|
50
|
+
delete: t("Del", "Delete"),
|
|
51
|
+
del: t("Del", "Delete")
|
|
52
|
+
};
|
|
53
|
+
function w() {
|
|
54
|
+
var a;
|
|
55
|
+
if (typeof navigator == "undefined")
|
|
56
|
+
return "other";
|
|
57
|
+
const e = (a = navigator.userAgentData) == null ? void 0 : a.platform;
|
|
58
|
+
return /mac|iphone|ipad|ipod/i.test(e || navigator.platform || "") ? "mac" : "other";
|
|
59
|
+
}
|
|
60
|
+
function x(e, a) {
|
|
61
|
+
var p;
|
|
62
|
+
const c = e.trim().toLowerCase() || e, m = (p = (a === "mac" ? d : i)[c]) != null ? p : s[c];
|
|
63
|
+
if (m)
|
|
64
|
+
return m;
|
|
65
|
+
const l = e.length === 1 ? e.toUpperCase() : e;
|
|
66
|
+
return { text: l, name: l };
|
|
67
|
+
}
|
|
68
|
+
export {
|
|
69
|
+
w as detectKbdPlatform,
|
|
70
|
+
x as kbdKeyLabel
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=kbdKeys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kbdKeys.js","sources":["../../../../src/components/dataDisplay/kbd/kbdKeys.ts"],"sourcesContent":["export type KbdPlatform = \"mac\" | \"other\";\n\n/** How one key is drawn, and how it is read out. */\nexport interface KbdKeyLabel {\n /** What is drawn on the key cap. */\n text: string;\n /** What assistive technology reads. */\n name: string;\n}\n\nconst arrow = (text: string, name: string): KbdKeyLabel => ({ text, name });\n\n// Names, in lower case, the same on every platform.\nconst COMMON: Record<string, KbdKeyLabel> = {\n up: arrow(\"↑\", \"Up arrow\"),\n arrowup: arrow(\"↑\", \"Up arrow\"),\n down: arrow(\"↓\", \"Down arrow\"),\n arrowdown: arrow(\"↓\", \"Down arrow\"),\n left: arrow(\"←\", \"Left arrow\"),\n arrowleft: arrow(\"←\", \"Left arrow\"),\n right: arrow(\"→\", \"Right arrow\"),\n arrowright: arrow(\"→\", \"Right arrow\"),\n // `KeyboardEvent.key` is \" \" for the space bar, and a bare \"+\" would read \"Ctrl++\".\n \" \": { text: \"Space\", name: \"Space\" },\n space: { text: \"Space\", name: \"Space\" },\n spacebar: { text: \"Space\", name: \"Space\" },\n \"+\": { text: \"+\", name: \"Plus\" },\n plus: { text: \"+\", name: \"Plus\" },\n};\n\nconst COMMAND: KbdKeyLabel = { text: \"⌘\", name: \"Command\" };\n\n// On macOS the modifiers and the editing keys are drawn as the symbols the Mac\n// keyboard and its menus use.\nconst MAC: Record<string, KbdKeyLabel> = {\n mod: COMMAND,\n meta: COMMAND,\n cmd: COMMAND,\n command: COMMAND,\n shift: { text: \"⇧\", name: \"Shift\" },\n alt: { text: \"⌥\", name: \"Option\" },\n option: { text: \"⌥\", name: \"Option\" },\n ctrl: { text: \"⌃\", name: \"Control\" },\n control: { text: \"⌃\", name: \"Control\" },\n enter: { text: \"↩\", name: \"Return\" },\n return: { text: \"↩\", name: \"Return\" },\n escape: { text: \"⎋\", name: \"Escape\" },\n esc: { text: \"⎋\", name: \"Escape\" },\n tab: { text: \"⇥\", name: \"Tab\" },\n backspace: { text: \"⌫\", name: \"Delete\" },\n delete: { text: \"⌦\", name: \"Forward delete\" },\n del: { text: \"⌦\", name: \"Forward delete\" },\n};\n\n// Elsewhere the same names are written in their usual capitalisation, so one `keys` array\n// looks alike on every platform. `Meta`, `Cmd` and `Command` have no key of their own here\n// and are drawn as `Meta`.\nconst META: KbdKeyLabel = { text: \"Meta\", name: \"Meta\" };\nconst named = (text: string, name = text): KbdKeyLabel => ({ text, name });\nconst OTHER: Record<string, KbdKeyLabel> = {\n mod: named(\"Ctrl\"),\n ctrl: named(\"Ctrl\"),\n control: named(\"Ctrl\"),\n alt: named(\"Alt\"),\n option: named(\"Alt\"),\n shift: named(\"Shift\"),\n meta: META,\n cmd: META,\n command: META,\n enter: named(\"Enter\"),\n return: named(\"Enter\"),\n escape: named(\"Esc\", \"Escape\"),\n esc: named(\"Esc\", \"Escape\"),\n tab: named(\"Tab\"),\n backspace: named(\"Backspace\"),\n delete: named(\"Del\", \"Delete\"),\n del: named(\"Del\", \"Delete\"),\n};\n\n/**\n * The platform of the running browser: `mac` for macOS (and iPadOS, which reports itself\n * so), `other` everywhere else and without a `navigator` (on the server).\n */\nexport function detectKbdPlatform(): KbdPlatform {\n if (typeof navigator === \"undefined\") {\n return \"other\";\n }\n const hinted = (navigator as Navigator & { userAgentData?: { platform?: string } }).userAgentData?.platform;\n return /mac|iphone|ipad|ipod/i.test(hinted || navigator.platform || \"\") ? \"mac\" : \"other\";\n}\n\n/**\n * The cap and the spoken name of a key. `Mod` is Command on `mac` and Ctrl on `other`; see the\n * tables above for the rest. A single letter is drawn in upper case; any other key as given.\n */\nexport function kbdKeyLabel(key: string, platform: KbdPlatform): KbdKeyLabel {\n const lower = key.trim().toLowerCase() || key; // a lone \" \" is the space bar\n const known = (platform === \"mac\" ? MAC : OTHER)[lower] ?? COMMON[lower];\n if (known) {\n return known;\n }\n const text = key.length === 1 ? key.toUpperCase() : key;\n return { text, name: text };\n}\n"],"names":["arrow","text","name","COMMON","COMMAND","MAC","META","named","OTHER","detectKbdPlatform","_a","hinted","kbdKeyLabel","key","platform","lower","known"],"mappings":"AAUA,MAAMA,IAAQ,CAACC,GAAcC,OAA+B,EAAE,MAAAD,GAAM,MAAAC,EAAA,IAG9DC,IAAsC;AAAA,EAC1C,IAAIH,EAAM,KAAK,UAAU;AAAA,EACzB,SAASA,EAAM,KAAK,UAAU;AAAA,EAC9B,MAAMA,EAAM,KAAK,YAAY;AAAA,EAC7B,WAAWA,EAAM,KAAK,YAAY;AAAA,EAClC,MAAMA,EAAM,KAAK,YAAY;AAAA,EAC7B,WAAWA,EAAM,KAAK,YAAY;AAAA,EAClC,OAAOA,EAAM,KAAK,aAAa;AAAA,EAC/B,YAAYA,EAAM,KAAK,aAAa;AAAA;AAAA,EAEpC,KAAK,EAAE,MAAM,SAAS,MAAM,QAAA;AAAA,EAC5B,OAAO,EAAE,MAAM,SAAS,MAAM,QAAA;AAAA,EAC9B,UAAU,EAAE,MAAM,SAAS,MAAM,QAAA;AAAA,EACjC,KAAK,EAAE,MAAM,KAAK,MAAM,OAAA;AAAA,EACxB,MAAM,EAAE,MAAM,KAAK,MAAM,OAAA;AAC3B,GAEMI,IAAuB,EAAE,MAAM,KAAK,MAAM,UAAA,GAI1CC,IAAmC;AAAA,EACvC,KAAKD;AAAA,EACL,MAAMA;AAAA,EACN,KAAKA;AAAA,EACL,SAASA;AAAA,EACT,OAAO,EAAE,MAAM,KAAK,MAAM,QAAA;AAAA,EAC1B,KAAK,EAAE,MAAM,KAAK,MAAM,SAAA;AAAA,EACxB,QAAQ,EAAE,MAAM,KAAK,MAAM,SAAA;AAAA,EAC3B,MAAM,EAAE,MAAM,KAAK,MAAM,UAAA;AAAA,EACzB,SAAS,EAAE,MAAM,KAAK,MAAM,UAAA;AAAA,EAC5B,OAAO,EAAE,MAAM,KAAK,MAAM,SAAA;AAAA,EAC1B,QAAQ,EAAE,MAAM,KAAK,MAAM,SAAA;AAAA,EAC3B,QAAQ,EAAE,MAAM,KAAK,MAAM,SAAA;AAAA,EAC3B,KAAK,EAAE,MAAM,KAAK,MAAM,SAAA;AAAA,EACxB,KAAK,EAAE,MAAM,KAAK,MAAM,MAAA;AAAA,EACxB,WAAW,EAAE,MAAM,KAAK,MAAM,SAAA;AAAA,EAC9B,QAAQ,EAAE,MAAM,KAAK,MAAM,iBAAA;AAAA,EAC3B,KAAK,EAAE,MAAM,KAAK,MAAM,iBAAA;AAC1B,GAKME,IAAoB,EAAE,MAAM,QAAQ,MAAM,OAAA,GAC1CC,IAAQ,CAACN,GAAcC,IAAOD,OAAuB,EAAE,MAAAA,GAAM,MAAAC,MAC7DM,IAAqC;AAAA,EACzC,KAAKD,EAAM,MAAM;AAAA,EACjB,MAAMA,EAAM,MAAM;AAAA,EAClB,SAASA,EAAM,MAAM;AAAA,EACrB,KAAKA,EAAM,KAAK;AAAA,EAChB,QAAQA,EAAM,KAAK;AAAA,EACnB,OAAOA,EAAM,OAAO;AAAA,EACpB,MAAMD;AAAA,EACN,KAAKA;AAAA,EACL,SAASA;AAAA,EACT,OAAOC,EAAM,OAAO;AAAA,EACpB,QAAQA,EAAM,OAAO;AAAA,EACrB,QAAQA,EAAM,OAAO,QAAQ;AAAA,EAC7B,KAAKA,EAAM,OAAO,QAAQ;AAAA,EAC1B,KAAKA,EAAM,KAAK;AAAA,EAChB,WAAWA,EAAM,WAAW;AAAA,EAC5B,QAAQA,EAAM,OAAO,QAAQ;AAAA,EAC7B,KAAKA,EAAM,OAAO,QAAQ;AAC5B;AAMO,SAASE,IAAiC;AAzEjD,MAAAC;AA0EE,MAAI,OAAO,aAAc;AACvB,WAAO;AAET,QAAMC,KAAUD,IAAA,UAAoE,kBAApE,gBAAAA,EAAmF;AACnG,SAAO,wBAAwB,KAAKC,KAAU,UAAU,YAAY,EAAE,IAAI,QAAQ;AACpF;AAMO,SAASC,EAAYC,GAAaC,GAAoC;AArF7E,MAAAJ;AAsFE,QAAMK,IAAQF,EAAI,KAAA,EAAO,iBAAiBA,GACpCG,KAASN,KAAAI,MAAa,QAAQT,IAAMG,GAAOO,CAAK,MAAvC,OAAAL,IAA4CP,EAAOY,CAAK;AACvE,MAAIC;AACF,WAAOA;AAET,QAAMf,IAAOY,EAAI,WAAW,IAAIA,EAAI,gBAAgBA;AACpD,SAAO,EAAE,MAAAZ,GAAM,MAAMA,EAAA;AACvB;"}
|
|
@@ -2,13 +2,47 @@ import React from "react";
|
|
|
2
2
|
export interface ListItemProps {
|
|
3
3
|
disabled?: boolean;
|
|
4
4
|
className?: string;
|
|
5
|
+
/**
|
|
6
|
+
* Paints the row as the current one. On a link row (with `href`) it also marks the link as the current page
|
|
7
|
+
* with `aria-current="page"`, because `aria-selected` is not a state a list item can have; on another row it
|
|
8
|
+
* stays `aria-selected`.
|
|
9
|
+
*/
|
|
5
10
|
selected?: boolean;
|
|
6
11
|
/** Compact row. */
|
|
7
12
|
dense?: boolean;
|
|
8
13
|
/** Render a bottom divider. */
|
|
9
14
|
divider?: boolean;
|
|
10
15
|
startAdornment?: React.ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* Trailing content. On a link row (with `href`) it sits beside the link, not inside it, so it can hold a control
|
|
18
|
+
* (a pin button, a toggle) without nesting it in the `<a>`; a click on it does not reach `onClick`.
|
|
19
|
+
*/
|
|
11
20
|
endAdornment?: React.ReactNode;
|
|
21
|
+
/**
|
|
22
|
+
* Makes the row a link: the `startAdornment` and the children sit in an `<a href>` that fills the row, so it can be
|
|
23
|
+
* focused with Tab, opened with middle click or copied. Keep the `startAdornment` non-interactive; a control
|
|
24
|
+
* belongs in the `endAdornment`. A disabled row has no `href`. A router takes the
|
|
25
|
+
* plain click in `onClick` with `event.preventDefault()`, and leaves a modified one (Ctrl, Meta, Shift,
|
|
26
|
+
* Alt, or a button other than the main one) to the browser, as a router's `Link` does.
|
|
27
|
+
*/
|
|
28
|
+
href?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Where the link (with `href`) opens. By default `"_blank"`: a new tab, as for `Button`. Pass `null` for an
|
|
31
|
+
* internal link: the `target` attribute is left out and the link opens in place. An empty string does the same; any other
|
|
32
|
+
* string is used as is.
|
|
33
|
+
*/
|
|
34
|
+
target?: string | null;
|
|
35
|
+
/**
|
|
36
|
+
* The `rel` of the link (with `href`). By default `"noreferrer"` for a link that opens another tab or window,
|
|
37
|
+
* and none for one that opens in place. Your own value replaces the default, so add `noreferrer` yourself
|
|
38
|
+
* if you still want it; an empty string drops the attribute.
|
|
39
|
+
*/
|
|
40
|
+
rel?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Click handler of the row. With an `href` it runs for a click on the link (not on the `endAdornment`), before the
|
|
43
|
+
* browser follows it, so `event.preventDefault()` cancels the navigation; the row then is not a Tab stop of its
|
|
44
|
+
* own, the link is.
|
|
45
|
+
*/
|
|
12
46
|
onClick?: React.MouseEventHandler<HTMLLIElement>;
|
|
13
47
|
}
|
|
14
48
|
export declare const ListItem: React.ForwardRefExoticComponent<ListItemProps & {
|
|
@@ -1,37 +1,60 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { forwardRef as
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { jsx as n, jsxs as a, Fragment as w } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as R, useRef as y } from "react";
|
|
3
|
+
import I from "clsx";
|
|
4
|
+
import { resolveLinkRel as j, resolveLinkTarget as D } from "../../../utils/linkAttrs.js";
|
|
5
|
+
const A = R(function({ className: p, children: b, disabled: i, selected: r, dense: h, divider: u, startAdornment: g, endAdornment: k, href: m, target: N, rel: x, onClick: t }, L) {
|
|
6
|
+
const s = !!m, l = !!t && !i && !s, _ = D(N), o = y(null), d = /* @__PURE__ */ n("span", { className: "smwb-list__item__start", children: g }), c = /* @__PURE__ */ n("span", { className: "smwb-list__item__main", children: b }), f = /* @__PURE__ */ n("span", { className: "smwb-list__item__end", children: k });
|
|
7
|
+
return /* @__PURE__ */ n(
|
|
7
8
|
"li",
|
|
8
9
|
{
|
|
9
|
-
ref:
|
|
10
|
+
ref: L,
|
|
10
11
|
role: "listitem",
|
|
11
|
-
tabIndex:
|
|
12
|
-
"aria-disabled":
|
|
13
|
-
"aria-selected":
|
|
14
|
-
onClick:
|
|
15
|
-
|
|
12
|
+
tabIndex: l ? 0 : void 0,
|
|
13
|
+
"aria-disabled": i || void 0,
|
|
14
|
+
"aria-selected": !s && r || void 0,
|
|
15
|
+
onClick: i || !t ? void 0 : s ? (e) => {
|
|
16
|
+
var v;
|
|
17
|
+
(v = o.current) != null && v.contains(e.target) && t(e);
|
|
18
|
+
} : t,
|
|
19
|
+
onKeyDown: l ? (e) => {
|
|
16
20
|
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), t == null || t(e));
|
|
17
21
|
} : void 0,
|
|
18
|
-
className:
|
|
19
|
-
"smwb-disabled":
|
|
20
|
-
"smwb-selected":
|
|
21
|
-
"smwb-
|
|
22
|
-
"smwb-
|
|
22
|
+
className: I("smwb-list__item", p, {
|
|
23
|
+
"smwb-disabled": i,
|
|
24
|
+
"smwb-selected": r,
|
|
25
|
+
"smwb-list__item_link": s,
|
|
26
|
+
"smwb-list__item_dense": h,
|
|
27
|
+
"smwb-list__item_divider": u
|
|
23
28
|
}),
|
|
24
29
|
"data-testid": "list-item",
|
|
25
|
-
children: [
|
|
26
|
-
/* @__PURE__ */
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
children: s ? /* @__PURE__ */ a(w, { children: [
|
|
31
|
+
/* @__PURE__ */ a(
|
|
32
|
+
"a",
|
|
33
|
+
{
|
|
34
|
+
ref: o,
|
|
35
|
+
className: "smwb-list__item__link",
|
|
36
|
+
"data-testid": "list-item-link",
|
|
37
|
+
"aria-current": r ? "page" : void 0,
|
|
38
|
+
href: i ? void 0 : m,
|
|
39
|
+
target: _,
|
|
40
|
+
rel: j(x, _),
|
|
41
|
+
children: [
|
|
42
|
+
d,
|
|
43
|
+
c
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
),
|
|
47
|
+
f
|
|
48
|
+
] }) : /* @__PURE__ */ a(w, { children: [
|
|
49
|
+
d,
|
|
50
|
+
c,
|
|
51
|
+
f
|
|
52
|
+
] })
|
|
30
53
|
}
|
|
31
54
|
);
|
|
32
55
|
});
|
|
33
56
|
export {
|
|
34
|
-
|
|
35
|
-
|
|
57
|
+
A as ListItem,
|
|
58
|
+
A as default
|
|
36
59
|
};
|
|
37
60
|
//# sourceMappingURL=listItem.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listItem.js","sources":["../../../../src/components/dataDisplay/list/listItem.tsx"],"sourcesContent":["import React, { forwardRef, PropsWithChildren } from \"react\";\nimport cn from \"clsx\";\n\nexport interface ListItemProps {\n disabled?: boolean;\n className?: string;\n selected?: boolean;\n /** Compact row. */\n dense?: boolean;\n /** Render a bottom divider. */\n divider?: boolean;\n startAdornment?: React.ReactNode;\n endAdornment?: React.ReactNode;\n onClick?: React.MouseEventHandler<HTMLLIElement>;\n}\n\nexport const ListItem = forwardRef<HTMLLIElement, PropsWithChildren<ListItemProps>>(function ListItem(\n { className, children, disabled, selected, dense, divider, startAdornment, endAdornment, onClick },\n ref\n) {\n const interactive = !!onClick && !disabled;\n\n return (\n <li\n ref={ref}\n role=\"listitem\"\n tabIndex={interactive ? 0 : undefined}\n aria-disabled={disabled || undefined}\n aria-selected={selected || undefined}\n onClick={
|
|
1
|
+
{"version":3,"file":"listItem.js","sources":["../../../../src/components/dataDisplay/list/listItem.tsx"],"sourcesContent":["import React, { forwardRef, PropsWithChildren, useRef } from \"react\";\nimport cn from \"clsx\";\nimport { resolveLinkRel, resolveLinkTarget } from \"../../../utils/linkAttrs\";\n\nexport interface ListItemProps {\n disabled?: boolean;\n className?: string;\n /**\n * Paints the row as the current one. On a link row (with `href`) it also marks the link as the current page\n * with `aria-current=\"page\"`, because `aria-selected` is not a state a list item can have; on another row it\n * stays `aria-selected`.\n */\n selected?: boolean;\n /** Compact row. */\n dense?: boolean;\n /** Render a bottom divider. */\n divider?: boolean;\n startAdornment?: React.ReactNode;\n /**\n * Trailing content. On a link row (with `href`) it sits beside the link, not inside it, so it can hold a control\n * (a pin button, a toggle) without nesting it in the `<a>`; a click on it does not reach `onClick`.\n */\n endAdornment?: React.ReactNode;\n /**\n * Makes the row a link: the `startAdornment` and the children sit in an `<a href>` that fills the row, so it can be\n * focused with Tab, opened with middle click or copied. Keep the `startAdornment` non-interactive; a control\n * belongs in the `endAdornment`. A disabled row has no `href`. A router takes the\n * plain click in `onClick` with `event.preventDefault()`, and leaves a modified one (Ctrl, Meta, Shift,\n * Alt, or a button other than the main one) to the browser, as a router's `Link` does.\n */\n href?: string;\n /**\n * Where the link (with `href`) opens. By default `\"_blank\"`: a new tab, as for `Button`. Pass `null` for an\n * internal link: the `target` attribute is left out and the link opens in place. An empty string does the same; any other\n * string is used as is.\n */\n target?: string | null;\n /**\n * The `rel` of the link (with `href`). By default `\"noreferrer\"` for a link that opens another tab or window,\n * and none for one that opens in place. Your own value replaces the default, so add `noreferrer` yourself\n * if you still want it; an empty string drops the attribute.\n */\n rel?: string;\n /**\n * Click handler of the row. With an `href` it runs for a click on the link (not on the `endAdornment`), before the\n * browser follows it, so `event.preventDefault()` cancels the navigation; the row then is not a Tab stop of its\n * own, the link is.\n */\n onClick?: React.MouseEventHandler<HTMLLIElement>;\n}\n\nexport const ListItem = forwardRef<HTMLLIElement, PropsWithChildren<ListItemProps>>(function ListItem(\n { className, children, disabled, selected, dense, divider, startAdornment, endAdornment, href, target, rel, onClick },\n ref\n) {\n const link = !!href;\n // A link row is focused through its anchor, which Enter follows by itself.\n const interactive = !!onClick && !disabled && !link;\n const linkTarget = resolveLinkTarget(target);\n const linkRef = useRef<HTMLAnchorElement>(null);\n const start = <span className=\"smwb-list__item__start\">{startAdornment}</span>;\n const main = <span className=\"smwb-list__item__main\">{children}</span>;\n const end = <span className=\"smwb-list__item__end\">{endAdornment}</span>;\n const handleClick: React.MouseEventHandler<HTMLLIElement> | undefined =\n disabled || !onClick\n ? undefined\n : link\n ? (e) => {\n // The end adornment is beside the link, and its own clicks are not the row's.\n if (linkRef.current?.contains(e.target as Node)) onClick(e);\n }\n : onClick;\n\n return (\n <li\n ref={ref}\n role=\"listitem\"\n tabIndex={interactive ? 0 : undefined}\n aria-disabled={disabled || undefined}\n aria-selected={(!link && selected) || undefined}\n onClick={handleClick}\n onKeyDown={\n interactive\n ? (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onClick?.(e as unknown as React.MouseEvent<HTMLLIElement>);\n }\n }\n : undefined\n }\n className={cn(\"smwb-list__item\", className, {\n \"smwb-disabled\": disabled,\n \"smwb-selected\": selected,\n \"smwb-list__item_link\": link,\n \"smwb-list__item_dense\": dense,\n \"smwb-list__item_divider\": divider,\n })}\n data-testid=\"list-item\"\n >\n {link ? (\n <>\n <a\n ref={linkRef}\n className=\"smwb-list__item__link\"\n data-testid=\"list-item-link\"\n aria-current={selected ? \"page\" : undefined}\n // A disabled link has no href, so it is no link to follow or to focus.\n href={disabled ? undefined : href}\n target={linkTarget}\n rel={resolveLinkRel(rel, linkTarget)}\n >\n {start}\n {main}\n </a>\n {end}\n </>\n ) : (\n <>\n {start}\n {main}\n {end}\n </>\n )}\n </li>\n );\n});\n\nexport default ListItem;\n"],"names":["ListItem","forwardRef","className","children","disabled","selected","dense","divider","startAdornment","endAdornment","href","target","rel","onClick","ref","link","interactive","linkTarget","resolveLinkTarget","linkRef","useRef","start","jsx","main","end","_a","cn","jsxs","Fragment","resolveLinkRel"],"mappings":";;;;AAmDO,MAAMA,IAAWC,EAA4D,SAClF,EAAE,WAAAC,GAAW,UAAAC,GAAU,UAAAC,GAAU,UAAAC,GAAU,OAAAC,GAAO,SAAAC,GAAS,gBAAAC,GAAgB,cAAAC,GAAc,MAAAC,GAAM,QAAAC,GAAQ,KAAAC,GAAK,SAAAC,EAAA,GAC5GC,GACA;AACA,QAAMC,IAAO,CAAC,CAACL,GAETM,IAAc,CAAC,CAACH,KAAW,CAACT,KAAY,CAACW,GACzCE,IAAaC,EAAkBP,CAAM,GACrCQ,IAAUC,EAA0B,IAAI,GACxCC,IAAQ,gBAAAC,EAAC,QAAA,EAAK,WAAU,0BAA0B,UAAAd,GAAe,GACjEe,IAAO,gBAAAD,EAAC,QAAA,EAAK,WAAU,yBAAyB,UAAAnB,GAAS,GACzDqB,IAAM,gBAAAF,EAAC,QAAA,EAAK,WAAU,wBAAwB,UAAAb,GAAa;AAWjE,SACE,gBAAAa;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAR;AAAA,MACA,MAAK;AAAA,MACL,UAAUE,IAAc,IAAI;AAAA,MAC5B,iBAAeZ,KAAY;AAAA,MAC3B,iBAAgB,CAACW,KAAQV,KAAa;AAAA,MACtC,SAhBFD,KAAY,CAACS,IACT,SACAE,IACE,CAAC,MAAM;;AAEL,SAAIU,IAAAN,EAAQ,YAAR,QAAAM,EAAiB,SAAS,EAAE,aAAyB,CAAC;AAAA,MAC5D,IACAZ;AAAA,MAUJ,WACEG,IACI,CAAC,MAAM;AACL,SAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,SACjC,EAAE,eAAA,GACFH,KAAA,QAAAA,EAAU;AAAA,MAEd,IACA;AAAA,MAEN,WAAWa,EAAG,mBAAmBxB,GAAW;AAAA,QAC1C,iBAAiBE;AAAA,QACjB,iBAAiBC;AAAA,QACjB,wBAAwBU;AAAA,QACxB,yBAAyBT;AAAA,QACzB,2BAA2BC;AAAA,MAAA,CAC5B;AAAA,MACD,eAAY;AAAA,MAEX,cACC,gBAAAoB,EAAAC,GAAA,EACE,UAAA;AAAA,QAAA,gBAAAD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAKR;AAAA,YACL,WAAU;AAAA,YACV,eAAY;AAAA,YACZ,gBAAcd,IAAW,SAAS;AAAA,YAElC,MAAMD,IAAW,SAAYM;AAAA,YAC7B,QAAQO;AAAA,YACR,KAAKY,EAAejB,GAAKK,CAAU;AAAA,YAElC,UAAA;AAAA,cAAAI;AAAA,cACAE;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAEFC;AAAA,MAAA,EAAA,CACH,IAEA,gBAAAG,EAAAC,GAAA,EACG,UAAA;AAAA,QAAAP;AAAA,QACAE;AAAA,QACAC;AAAA,MAAA,EAAA,CACH;AAAA,IAAA;AAAA,EAAA;AAIR,CAAC;"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/** Error-correction level: L 7%, M 15%, Q 25%, H 30% of the code may be damaged or covered. */
|
|
3
|
+
export type QrCodeErrorCorrection = "L" | "M" | "Q" | "H";
|
|
4
|
+
export interface QrCodeProps extends Omit<React.HTMLAttributes<HTMLElement>, "children" | "role"> {
|
|
5
|
+
/** Text encoded in the code (a URL, a pairing token). Encoded as UTF-8 bytes. */
|
|
6
|
+
value: string;
|
|
7
|
+
/** Side of the code, quiet zone included, in pixels. Default 192. */
|
|
8
|
+
size?: number | undefined;
|
|
9
|
+
/** Shown under the code (a `<figcaption>`), e.g. "Scan with the phone app". */
|
|
10
|
+
caption?: React.ReactNode;
|
|
11
|
+
/** Accessible name of the image. Default "QR code". */
|
|
12
|
+
label?: string | undefined;
|
|
13
|
+
/** Error-correction level: L 7%, M 15% (default), Q 25%, H 30% of the code may be damaged or covered. */
|
|
14
|
+
errorCorrection?: QrCodeErrorCorrection | undefined;
|
|
15
|
+
/** Light margin around the code in modules. Default 4, the minimum the QR spec asks for; smaller values hurt scanning. */
|
|
16
|
+
quietZone?: number | undefined;
|
|
17
|
+
/** Test id of the root; `qr-code` unless given. */
|
|
18
|
+
"data-testid"?: string | undefined;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A QR code of `value` as an SVG image (role=img): dark modules on a white square —
|
|
22
|
+
* including the quiet zone — in every theme, so a phone camera reads it in dark mode
|
|
23
|
+
* too. With `caption` the code sits in a `<figure>` named by the caption. A `value`
|
|
24
|
+
* past the QR capacity renders an empty white square with `data-error="too-long"`,
|
|
25
|
+
* any other encode failure with `data-error="encode-failed"`, instead of throwing.
|
|
26
|
+
*/
|
|
27
|
+
export declare const QrCode: React.ForwardRefExoticComponent<QrCodeProps & React.RefAttributes<HTMLElement>>;
|
|
28
|
+
export default QrCode;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { jsxs as f, jsx as d } from "react/jsx-runtime";
|
|
2
|
+
import '../../../assets/styles/less/components/qrCode/qrCode.entry.css';import '../../../assets/styles/less/tokens.entry.css';/* empty css */
|
|
3
|
+
/* empty css */
|
|
4
|
+
import { forwardRef as A, useMemo as E } from "react";
|
|
5
|
+
import N from "clsx";
|
|
6
|
+
import { encode as q } from "uqr";
|
|
7
|
+
import { qrCodePath as v } from "./qrCodePath.js";
|
|
8
|
+
const x = {
|
|
9
|
+
"too-long": "QR code: value too long",
|
|
10
|
+
"encode-failed": "QR code: value could not be encoded"
|
|
11
|
+
}, M = 32, w = 256;
|
|
12
|
+
var p;
|
|
13
|
+
const r = (p = globalThis.__smwbQrCodeWarnings) != null ? p : globalThis.__smwbQrCodeWarnings = /* @__PURE__ */ new Set(), b = (e, o) => {
|
|
14
|
+
r.has(e) || r.size >= M || (r.add(e), console.error(`[smwb] QrCode: ${o}`));
|
|
15
|
+
}, S = (e, o) => {
|
|
16
|
+
if (e instanceof RangeError && /too long/i.test(e.message)) {
|
|
17
|
+
const s = Math.ceil(o.length / w);
|
|
18
|
+
return b(
|
|
19
|
+
`too-long:${s}`,
|
|
20
|
+
`value is too long to encode as a QR code (${o.length} characters; this notice is once per ${w}-character band)`
|
|
21
|
+
), "too-long";
|
|
22
|
+
}
|
|
23
|
+
const t = e instanceof Error ? `${e.name}: ${e.message}` : String(e);
|
|
24
|
+
return b(`failed:${t}`, `value could not be encoded as a QR code (${t})`), "encode-failed";
|
|
25
|
+
}, U = A(function({
|
|
26
|
+
className: o,
|
|
27
|
+
value: t,
|
|
28
|
+
size: s = 192,
|
|
29
|
+
caption: l,
|
|
30
|
+
label: _ = "QR code",
|
|
31
|
+
errorCorrection: i = "M",
|
|
32
|
+
quietZone: m = 4,
|
|
33
|
+
"data-testid": C = "qr-code",
|
|
34
|
+
...R
|
|
35
|
+
}, $) {
|
|
36
|
+
var u, h;
|
|
37
|
+
const a = E(() => {
|
|
38
|
+
try {
|
|
39
|
+
return { modules: q(t, { ecc: i, border: 0 }).data, failure: null };
|
|
40
|
+
} catch (Q) {
|
|
41
|
+
return { modules: null, failure: S(Q, t) };
|
|
42
|
+
}
|
|
43
|
+
}, [t, i]), c = ((h = (u = a.modules) == null ? void 0 : u.length) != null ? h : 0) + 2 * m, g = a.modules ? v(a.modules, m) : "", n = a.failure;
|
|
44
|
+
return /* @__PURE__ */ f(
|
|
45
|
+
"figure",
|
|
46
|
+
{
|
|
47
|
+
...R,
|
|
48
|
+
ref: $,
|
|
49
|
+
"data-testid": C,
|
|
50
|
+
"data-error": n != null ? n : void 0,
|
|
51
|
+
className: N("smwb-qr-code", o),
|
|
52
|
+
children: [
|
|
53
|
+
/* @__PURE__ */ f(
|
|
54
|
+
"svg",
|
|
55
|
+
{
|
|
56
|
+
className: "smwb-qr-code__image",
|
|
57
|
+
role: "img",
|
|
58
|
+
"aria-label": n === null ? _ : x[n],
|
|
59
|
+
viewBox: `0 0 ${c} ${c}`,
|
|
60
|
+
width: s,
|
|
61
|
+
height: s,
|
|
62
|
+
shapeRendering: "crispEdges",
|
|
63
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
64
|
+
children: [
|
|
65
|
+
/* @__PURE__ */ d("rect", { className: "smwb-qr-code__light", width: c, height: c, fill: "rgb(255,255,255)" }),
|
|
66
|
+
g && /* @__PURE__ */ d("path", { className: "smwb-qr-code__dark", d: g, fill: "rgb(0,0,0)" })
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
),
|
|
70
|
+
l ? /* @__PURE__ */ d("figcaption", { className: "smwb-qr-code__caption", children: l }) : null
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
export {
|
|
76
|
+
U as QrCode
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=qrCode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qrCode.js","sources":["../../../../src/components/dataDisplay/qrCode/qrCode.tsx"],"sourcesContent":["import React, { forwardRef, useMemo } from \"react\";\nimport cn from \"clsx\";\nimport { encode } from \"uqr\";\nimport { qrCodePath } from \"./qrCodePath\";\n\n/** Error-correction level: L 7%, M 15%, Q 25%, H 30% of the code may be damaged or covered. */\nexport type QrCodeErrorCorrection = \"L\" | \"M\" | \"Q\" | \"H\";\n\nexport interface QrCodeProps extends Omit<React.HTMLAttributes<HTMLElement>, \"children\" | \"role\"> {\n /** Text encoded in the code (a URL, a pairing token). Encoded as UTF-8 bytes. */\n value: string;\n /** Side of the code, quiet zone included, in pixels. Default 192. */\n size?: number | undefined;\n /** Shown under the code (a `<figcaption>`), e.g. \"Scan with the phone app\". */\n caption?: React.ReactNode;\n /** Accessible name of the image. Default \"QR code\". */\n label?: string | undefined;\n /** Error-correction level: L 7%, M 15% (default), Q 25%, H 30% of the code may be damaged or covered. */\n errorCorrection?: QrCodeErrorCorrection | undefined;\n /** Light margin around the code in modules. Default 4, the minimum the QR spec asks for; smaller values hurt scanning. */\n quietZone?: number | undefined;\n /** Test id of the root; `qr-code` unless given. */\n \"data-testid\"?: string | undefined;\n}\n\n// Why the encoding failed, as the root's `data-error`, and the name the image takes then.\ntype QrCodeFailure = \"too-long\" | \"encode-failed\";\nconst FAILURE_LABEL: Record<QrCodeFailure, string> = {\n \"too-long\": \"QR code: value too long\",\n \"encode-failed\": \"QR code: value could not be encoded\",\n};\n\n// Warns once per distinct cause, never per value: the registry keys on the cause the\n// message reports — a capacity band, or the error text — not on the value, so a\n// `QrCode` bound to a text field neither keeps a multi-KB string alive per keystroke nor\n// logs a new line for every character typed. The cap bounds the registry itself: past it\n// the warning stays quiet instead of growing. It lives on globalThis so the server bundle\n// and the client module of one SSR runtime share it: the cause logs once per runtime, not\n// once per bundle. A process.env guard is deliberately not used — like dagView.tsx it\n// would silence only dev SSR.\nconst MAX_WARNED_CAUSES = 32;\nconst CAPACITY_BAND = 256; // characters: one notice per band, not per length\nconst warnedCauses = ((globalThis as { __smwbQrCodeWarnings?: Set<string> }).__smwbQrCodeWarnings ??= new Set());\nconst warnOnce = (cause: string, message: string): void => {\n if (warnedCauses.has(cause) || warnedCauses.size >= MAX_WARNED_CAUSES) {\n return;\n }\n warnedCauses.add(cause);\n // eslint-disable-next-line no-console\n console.error(`[smwb] QrCode: ${message}`);\n};\n\n// `uqr` reports a value past the QR capacity as a RangeError(\"Data too long\"); it throws\n// other errors for other inputs (a lone surrogate fails in `encodeURI`, an untyped\n// `errorCorrection` fails in its own lookup). Only the first of those is \"too long\", so\n// the failure is read off the error instead of assumed, and the rest are named as what\n// they are.\nconst noteEncodeFailure = (error: unknown, value: string): QrCodeFailure => {\n if (error instanceof RangeError && /too long/i.test(error.message)) {\n const band = Math.ceil(value.length / CAPACITY_BAND);\n warnOnce(\n `too-long:${band}`,\n `value is too long to encode as a QR code (${value.length} characters; this notice is once per ` +\n `${CAPACITY_BAND}-character band)`\n );\n return \"too-long\";\n }\n const reason = error instanceof Error ? `${error.name}: ${error.message}` : String(error);\n warnOnce(`failed:${reason}`, `value could not be encoded as a QR code (${reason})`);\n return \"encode-failed\";\n};\n\n/**\n * A QR code of `value` as an SVG image (role=img): dark modules on a white square —\n * including the quiet zone — in every theme, so a phone camera reads it in dark mode\n * too. With `caption` the code sits in a `<figure>` named by the caption. A `value`\n * past the QR capacity renders an empty white square with `data-error=\"too-long\"`,\n * any other encode failure with `data-error=\"encode-failed\"`, instead of throwing.\n */\nexport const QrCode = forwardRef<HTMLElement, QrCodeProps>(function QrCode(\n {\n className,\n value,\n size = 192,\n caption,\n label = \"QR code\",\n errorCorrection = \"M\",\n quietZone = 4,\n \"data-testid\": dataTestId = \"qr-code\",\n ...rest\n },\n ref\n) {\n const encoded = useMemo(() => {\n try {\n return { modules: encode(value, { ecc: errorCorrection, border: 0 }).data, failure: null };\n } catch (error) {\n return { modules: null, failure: noteEncodeFailure(error, value) };\n }\n }, [value, errorCorrection]);\n\n // N: the whole canvas in modules — matrix plus the quiet zone on every side.\n const moduleCount = encoded.modules?.length ?? 0;\n const canvas = moduleCount + 2 * quietZone;\n const path = encoded.modules ? qrCodePath(encoded.modules, quietZone) : \"\";\n const failure = encoded.failure;\n\n return (\n <figure\n {...rest}\n ref={ref}\n data-testid={dataTestId}\n data-error={failure ?? undefined}\n className={cn(\"smwb-qr-code\", className)}\n >\n <svg\n className=\"smwb-qr-code__image\"\n role=\"img\"\n aria-label={failure === null ? label : FAILURE_LABEL[failure]}\n viewBox={`0 0 ${canvas} ${canvas}`}\n width={size}\n height={size}\n shapeRendering=\"crispEdges\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <rect className=\"smwb-qr-code__light\" width={canvas} height={canvas} fill=\"rgb(255,255,255)\" />\n {path && <path className=\"smwb-qr-code__dark\" d={path} fill=\"rgb(0,0,0)\" />}\n </svg>\n {caption ? <figcaption className=\"smwb-qr-code__caption\">{caption}</figcaption> : null}\n </figure>\n );\n});\n\nexport default QrCode;\n"],"names":["FAILURE_LABEL","MAX_WARNED_CAUSES","CAPACITY_BAND","warnedCauses","_a","warnOnce","cause","message","noteEncodeFailure","error","value","band","reason","QrCode","forwardRef","className","size","caption","label","errorCorrection","quietZone","dataTestId","rest","ref","encoded","useMemo","encode","canvas","_b","path","qrCodePath","failure","jsxs","cn","jsx"],"mappings":";;;;;;;AA6BA,MAAMA,IAA+C;AAAA,EACnD,YAAY;AAAA,EACZ,iBAAiB;AACnB,GAUMC,IAAoB,IACpBC,IAAgB;;AACtB,MAAMC,KAAiBC,IAAA,WAAsD,yBAAtD,OAAAA,IAAA,WAAsD,uBAAyB,oBAAI,IAAA,GACpGC,IAAW,CAACC,GAAeC,MAA0B;AACzD,EAAIJ,EAAa,IAAIG,CAAK,KAAKH,EAAa,QAAQF,MAGpDE,EAAa,IAAIG,CAAK,GAEtB,QAAQ,MAAM,kBAAkBC,CAAO,EAAE;AAC3C,GAOMC,IAAoB,CAACC,GAAgBC,MAAiC;AAC1E,MAAID,aAAiB,cAAc,YAAY,KAAKA,EAAM,OAAO,GAAG;AAClE,UAAME,IAAO,KAAK,KAAKD,EAAM,SAASR,CAAa;AACnD,WAAAG;AAAA,MACE,YAAYM,CAAI;AAAA,MAChB,6CAA6CD,EAAM,MAAM,wCACpDR,CAAa;AAAA,IAAA,GAEb;AAAA,EACT;AACA,QAAMU,IAASH,aAAiB,QAAQ,GAAGA,EAAM,IAAI,KAAKA,EAAM,OAAO,KAAK,OAAOA,CAAK;AACxF,SAAAJ,EAAS,UAAUO,CAAM,IAAI,4CAA4CA,CAAM,GAAG,GAC3E;AACT,GASaC,IAASC,EAAqC,SACzD;AAAA,EACE,WAAAC;AAAA,EACA,OAAAL;AAAA,EACA,MAAAM,IAAO;AAAA,EACP,SAAAC;AAAA,EACA,OAAAC,IAAQ;AAAA,EACR,iBAAAC,IAAkB;AAAA,EAClB,WAAAC,IAAY;AAAA,EACZ,eAAeC,IAAa;AAAA,EAC5B,GAAGC;AACL,GACAC,GACA;;AACA,QAAMC,IAAUC,EAAQ,MAAM;AAC5B,QAAI;AACF,aAAO,EAAE,SAASC,EAAOhB,GAAO,EAAE,KAAKS,GAAiB,QAAQ,EAAA,CAAG,EAAE,MAAM,SAAS,KAAA;AAAA,IACtF,SAASV,GAAO;AACd,aAAO,EAAE,SAAS,MAAM,SAASD,EAAkBC,GAAOC,CAAK,EAAA;AAAA,IACjE;AAAA,EACF,GAAG,CAACA,GAAOS,CAAe,CAAC,GAIrBQ,MADcC,KAAAxB,IAAAoB,EAAQ,YAAR,gBAAApB,EAAiB,WAAjB,OAAAwB,IAA2B,KAClB,IAAIR,GAC3BS,IAAOL,EAAQ,UAAUM,EAAWN,EAAQ,SAASJ,CAAS,IAAI,IAClEW,IAAUP,EAAQ;AAExB,SACE,gBAAAQ;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAGV;AAAA,MACJ,KAAAC;AAAA,MACA,eAAaF;AAAA,MACb,cAAYU,KAAA,OAAAA,IAAW;AAAA,MACvB,WAAWE,EAAG,gBAAgBlB,CAAS;AAAA,MAEvC,UAAA;AAAA,QAAA,gBAAAiB;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAK;AAAA,YACL,cAAYD,MAAY,OAAOb,IAAQlB,EAAc+B,CAAO;AAAA,YAC5D,SAAS,OAAOJ,CAAM,IAAIA,CAAM;AAAA,YAChC,OAAOX;AAAA,YACP,QAAQA;AAAA,YACR,gBAAe;AAAA,YACf,OAAM;AAAA,YAEN,UAAA;AAAA,cAAA,gBAAAkB,EAAC,QAAA,EAAK,WAAU,uBAAsB,OAAOP,GAAQ,QAAQA,GAAQ,MAAK,mBAAA,CAAmB;AAAA,cAC5FE,uBAAS,QAAA,EAAK,WAAU,sBAAqB,GAAGA,GAAM,MAAK,aAAA,CAAa;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAE1EZ,IAAU,gBAAAiB,EAAC,cAAA,EAAW,WAAU,yBAAyB,aAAQ,IAAgB;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGxF,CAAC;"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `d` string of the QR code's dark modules: one run-length subpath per horizontal
|
|
3
|
+
* run of dark modules (`M{x} {y}h{n}v1h-{n}z`), in row order and offset by the quiet
|
|
4
|
+
* zone. Pure and deterministic — the same matrix always yields the same string, on the
|
|
5
|
+
* server and in the browser, in ui-react and ui-solid.
|
|
6
|
+
*/
|
|
7
|
+
export declare function qrCodePath(data: readonly (readonly boolean[])[], quietZone: number): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
function i(n, o) {
|
|
2
|
+
const r = [];
|
|
3
|
+
for (let l = 0; l < n.length; l += 1) {
|
|
4
|
+
const h = n[l];
|
|
5
|
+
let e = 0;
|
|
6
|
+
for (; h !== void 0 && e < h.length; )
|
|
7
|
+
if (h[e]) {
|
|
8
|
+
let t = 1;
|
|
9
|
+
for (; e + t < h.length && h[e + t]; )
|
|
10
|
+
t += 1;
|
|
11
|
+
r.push(`M${e + o} ${l + o}h${t}v1h-${t}z`), e += t;
|
|
12
|
+
} else
|
|
13
|
+
e += 1;
|
|
14
|
+
}
|
|
15
|
+
return r.join("");
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
i as qrCodePath
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=qrCodePath.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qrCodePath.js","sources":["../../../../src/components/dataDisplay/qrCode/qrCodePath.ts"],"sourcesContent":["/**\n * The `d` string of the QR code's dark modules: one run-length subpath per horizontal\n * run of dark modules (`M{x} {y}h{n}v1h-{n}z`), in row order and offset by the quiet\n * zone. Pure and deterministic — the same matrix always yields the same string, on the\n * server and in the browser, in ui-react and ui-solid.\n */\nexport function qrCodePath(data: readonly (readonly boolean[])[], quietZone: number): string {\n const parts: string[] = [];\n for (let y = 0; y < data.length; y += 1) {\n const row = data[y];\n let x = 0;\n while (row !== undefined && x < row.length) {\n if (row[x]) {\n let run = 1;\n while (x + run < row.length && row[x + run]) {\n run += 1;\n }\n parts.push(`M${x + quietZone} ${y + quietZone}h${run}v1h-${run}z`);\n x += run;\n } else {\n x += 1;\n }\n }\n }\n return parts.join(\"\");\n}\n"],"names":["qrCodePath","data","quietZone","parts","y","row","x","run"],"mappings":"AAMO,SAASA,EAAWC,GAAuCC,GAA2B;AAC3F,QAAMC,IAAkB,CAAA;AACxB,WAASC,IAAI,GAAGA,IAAIH,EAAK,QAAQG,KAAK,GAAG;AACvC,UAAMC,IAAMJ,EAAKG,CAAC;AAClB,QAAIE,IAAI;AACR,WAAOD,MAAQ,UAAaC,IAAID,EAAI;AAClC,UAAIA,EAAIC,CAAC,GAAG;AACV,YAAIC,IAAM;AACV,eAAOD,IAAIC,IAAMF,EAAI,UAAUA,EAAIC,IAAIC,CAAG;AACxC,UAAAA,KAAO;AAET,QAAAJ,EAAM,KAAK,IAAIG,IAAIJ,CAAS,IAAIE,IAAIF,CAAS,IAAIK,CAAG,OAAOA,CAAG,GAAG,GACjED,KAAKC;AAAA,MACP;AACE,QAAAD,KAAK;AAAA,EAGX;AACA,SAAOH,EAAM,KAAK,EAAE;AACtB;"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React, { HTMLAttributes } from "react";
|
|
2
|
+
/** What the marker says: `active` is under way, `attention` waits for someone, `idle` rests, `done` is finished. */
|
|
3
|
+
export type StatusDotStatus = "active" | "attention" | "idle" | "done" | "error" | "unknown";
|
|
4
|
+
/** The theme colour names `Chip` takes; `default` is the neutral on-surface colour. */
|
|
5
|
+
export type StatusDotColor = "default" | "primary" | "secondary" | "error" | "success" | "warning" | "info";
|
|
6
|
+
export type StatusDotSize = "sm" | "md";
|
|
7
|
+
export interface StatusDotProps extends Omit<HTMLAttributes<HTMLSpanElement>, "role" | "children" | "aria-label"> {
|
|
8
|
+
/** Class name(s) for the dot's root `<span>`. */
|
|
9
|
+
className?: string;
|
|
10
|
+
/**
|
|
11
|
+
* What the dot says, and so its colour: `active` info, `attention` warning, `idle` neutral, `done` success,
|
|
12
|
+
* `error` error. `unknown` is a ring in the outline colour. Without `status` (and without `color`) the dot is
|
|
13
|
+
* `unknown`.
|
|
14
|
+
*/
|
|
15
|
+
status?: StatusDotStatus | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* A theme colour instead of the status's own, or on its own with no `status` (a plain disc). Given with a
|
|
18
|
+
* `status`, the status still sets the shape.
|
|
19
|
+
*/
|
|
20
|
+
color?: StatusDotColor | undefined;
|
|
21
|
+
/** `md` (12px) unless given; `sm` is 8px. */
|
|
22
|
+
size?: StatusDotSize | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* A ring spreads from the dot. On unless given for `active`, off for every other status. Never drawn while the
|
|
25
|
+
* user prefers reduced motion.
|
|
26
|
+
*/
|
|
27
|
+
pulse?: boolean | undefined;
|
|
28
|
+
/** What the dot means in words, e.g. "Working": the accessible name, read by assistive technology. */
|
|
29
|
+
label: string;
|
|
30
|
+
/** Test id of the root; `status-dot` unless given. */
|
|
31
|
+
"data-testid"?: string | undefined;
|
|
32
|
+
}
|
|
33
|
+
/** A small status marker: a dot coloured and shaped by `status`, named by `label`. */
|
|
34
|
+
export declare const StatusDot: React.ForwardRefExoticComponent<StatusDotProps & React.RefAttributes<HTMLSpanElement>>;
|
|
35
|
+
export default StatusDot;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import '../../../assets/styles/less/components/statusDot/statusDot.entry.css';import '../../../assets/styles/less/tokens.entry.css';/* empty css */
|
|
3
|
+
/* empty css */
|
|
4
|
+
import { forwardRef as b } from "react";
|
|
5
|
+
import f from "clsx";
|
|
6
|
+
const x = b(function({ className: m, status: t, color: o, size: d = "md", pulse: s, label: i, "data-testid": r = "status-dot", ...n }, w) {
|
|
7
|
+
const a = t != null ? t : o === void 0 ? "unknown" : void 0;
|
|
8
|
+
return /* @__PURE__ */ e(
|
|
9
|
+
"span",
|
|
10
|
+
{
|
|
11
|
+
...n,
|
|
12
|
+
ref: w,
|
|
13
|
+
role: "img",
|
|
14
|
+
"aria-label": i,
|
|
15
|
+
"data-testid": r,
|
|
16
|
+
className: f(
|
|
17
|
+
"smwb-status-dot",
|
|
18
|
+
`smwb-status-dot_size-${d}`,
|
|
19
|
+
a && `smwb-status-dot_status-${a}`,
|
|
20
|
+
o && `smwb-status-dot_color-${o}`,
|
|
21
|
+
{ "smwb-status-dot_pulse": s != null ? s : t === "active" },
|
|
22
|
+
m
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
export {
|
|
28
|
+
x as StatusDot
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=statusDot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statusDot.js","sources":["../../../../src/components/dataDisplay/statusDot/statusDot.tsx"],"sourcesContent":["import React, { forwardRef, HTMLAttributes } from \"react\";\nimport cn from \"clsx\";\n\n/** What the marker says: `active` is under way, `attention` waits for someone, `idle` rests, `done` is finished. */\nexport type StatusDotStatus = \"active\" | \"attention\" | \"idle\" | \"done\" | \"error\" | \"unknown\";\n\n/** The theme colour names `Chip` takes; `default` is the neutral on-surface colour. */\nexport type StatusDotColor = \"default\" | \"primary\" | \"secondary\" | \"error\" | \"success\" | \"warning\" | \"info\";\n\nexport type StatusDotSize = \"sm\" | \"md\";\n\nexport interface StatusDotProps extends Omit<HTMLAttributes<HTMLSpanElement>, \"role\" | \"children\" | \"aria-label\"> {\n /** Class name(s) for the dot's root `<span>`. */\n className?: string;\n /**\n * What the dot says, and so its colour: `active` info, `attention` warning, `idle` neutral, `done` success,\n * `error` error. `unknown` is a ring in the outline colour. Without `status` (and without `color`) the dot is\n * `unknown`.\n */\n status?: StatusDotStatus | undefined;\n /**\n * A theme colour instead of the status's own, or on its own with no `status` (a plain disc). Given with a\n * `status`, the status still sets the shape.\n */\n color?: StatusDotColor | undefined;\n /** `md` (12px) unless given; `sm` is 8px. */\n size?: StatusDotSize | undefined;\n /**\n * A ring spreads from the dot. On unless given for `active`, off for every other status. Never drawn while the\n * user prefers reduced motion.\n */\n pulse?: boolean | undefined;\n /** What the dot means in words, e.g. \"Working\": the accessible name, read by assistive technology. */\n label: string;\n /** Test id of the root; `status-dot` unless given. */\n \"data-testid\"?: string | undefined;\n}\n\n/** A small status marker: a dot coloured and shaped by `status`, named by `label`. */\nexport const StatusDot = forwardRef<HTMLSpanElement, StatusDotProps>(function StatusDot(\n { className, status, color, size = \"md\", pulse, label, \"data-testid\": dataTestId = \"status-dot\", ...rest },\n ref\n) {\n // A bare colour is a plain disc; with neither, the dot is \"unknown\".\n const shown = status ?? (color === undefined ? \"unknown\" : undefined);\n return (\n <span\n {...rest}\n ref={ref}\n role=\"img\"\n aria-label={label}\n data-testid={dataTestId}\n className={cn(\n \"smwb-status-dot\",\n `smwb-status-dot_size-${size}`,\n shown && `smwb-status-dot_status-${shown}`,\n color && `smwb-status-dot_color-${color}`,\n { \"smwb-status-dot_pulse\": pulse ?? status === \"active\" },\n className\n )}\n />\n );\n});\n\nexport default StatusDot;\n"],"names":["StatusDot","forwardRef","className","status","color","size","pulse","label","dataTestId","rest","ref","shown","jsx","cn"],"mappings":";;;;;AAyCO,MAAMA,IAAYC,EAA4C,SACnE,EAAE,WAAAC,GAAW,QAAAC,GAAQ,OAAAC,GAAO,MAAAC,IAAO,MAAM,OAAAC,GAAO,OAAAC,GAAO,eAAeC,IAAa,cAAc,GAAGC,EAAA,GACpGC,GACA;AAEA,QAAMC,IAAQR,KAAA,OAAAA,IAAWC,MAAU,SAAY,YAAY;AAC3D,SACE,gBAAAQ;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAGH;AAAA,MACJ,KAAAC;AAAA,MACA,MAAK;AAAA,MACL,cAAYH;AAAA,MACZ,eAAaC;AAAA,MACb,WAAWK;AAAA,QACT;AAAA,QACA,wBAAwBR,CAAI;AAAA,QAC5BM,KAAS,0BAA0BA,CAAK;AAAA,QACxCP,KAAS,yBAAyBA,CAAK;AAAA,QACvC,EAAE,yBAAyBE,KAAA,OAAAA,IAASH,MAAW,SAAA;AAAA,QAC/CD;AAAA,MAAA;AAAA,IACF;AAAA,EAAA;AAGN,CAAC;"}
|