@monimesl/dot-renderer-react 1.0.0-beta.1 → 1.0.0-beta.10

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 (58) hide show
  1. package/README.md +3 -3
  2. package/dist/components/amount-input.js +1 -1
  3. package/dist/components/avatar.js +1 -1
  4. package/dist/components/box.js +9 -3
  5. package/dist/components/button.js +64 -14
  6. package/dist/components/carousel.js +65 -50
  7. package/dist/components/chip.js +4 -5
  8. package/dist/components/code-input.js +1 -1
  9. package/dist/components/detail-row.js +5 -5
  10. package/dist/components/disclosure.js +11 -6
  11. package/dist/components/empty-state.js +7 -6
  12. package/dist/components/feedback.js +7 -7
  13. package/dist/components/field-box.js +1 -1
  14. package/dist/components/field.js +5 -4
  15. package/dist/components/footer.js +6 -11
  16. package/dist/components/grid.js +25 -15
  17. package/dist/components/hidden-view.js +5 -0
  18. package/dist/components/icon-button.js +1 -1
  19. package/dist/components/icon.js +32 -5
  20. package/dist/components/index.d.ts +2 -1
  21. package/dist/components/index.js +3 -1
  22. package/dist/components/input.js +1 -1
  23. package/dist/components/link.js +11 -3
  24. package/dist/components/list.js +62 -33
  25. package/dist/components/option.js +6 -5
  26. package/dist/components/padding.js +9 -10
  27. package/dist/components/pinned-bar.js +29 -0
  28. package/dist/components/pinned.d.ts +6 -0
  29. package/dist/components/pinned.js +26 -0
  30. package/dist/components/pressable.js +3 -1
  31. package/dist/components/prose.js +23 -20
  32. package/dist/components/rich-text.js +30 -18
  33. package/dist/components/scroll.js +33 -10
  34. package/dist/components/select.js +1 -1
  35. package/dist/components/sheet.js +55 -46
  36. package/dist/components/side-room.js +5 -0
  37. package/dist/components/skeleton.js +1 -1
  38. package/dist/components/slider.js +3 -3
  39. package/dist/components/spinner.js +1 -1
  40. package/dist/components/stack.js +12 -8
  41. package/dist/components/stepper.js +4 -5
  42. package/dist/components/steps.js +17 -14
  43. package/dist/components/tabs.js +74 -27
  44. package/dist/components/text.js +12 -14
  45. package/dist/components/toast.js +3 -3
  46. package/dist/components/toggles.js +14 -11
  47. package/dist/components/tokens.d.ts +16 -0
  48. package/dist/components/tokens.js +26 -1
  49. package/dist/components/view.js +40 -18
  50. package/dist/index.d.ts +2 -1
  51. package/dist/index.js +2 -1
  52. package/dist/page-root.js +9 -3
  53. package/dist/pull-to-refresh.js +1 -1
  54. package/dist/root.js +4 -3
  55. package/dist/styles.css +1 -1
  56. package/dist/theme.d.ts +12 -1
  57. package/dist/theme.js +85 -15
  58. package/package.json +4 -4
@@ -1,55 +1,67 @@
1
1
  import { useTheme } from "../theme.js";
2
- import { Divider } from "./divider.js";
3
- import { Image } from "./image.js";
2
+ import { Divider as Divider$1 } from "./divider.js";
3
+ import { Image as Image$2 } from "./image.js";
4
4
  import { isHttps } from "./https.js";
5
- import { Link } from "./link.js";
6
- import { Bullet, BulletList, Prose, Quote } from "./prose.js";
5
+ import { Link as Link$2 } from "./link.js";
6
+ import { Bullet as Bullet$1, BulletList as BulletList$1, Prose as Prose$2, Quote as Quote$1 } from "./prose.js";
7
7
  import { parseMarkdown } from "../markdown.js";
8
- import { Text } from "./text.js";
8
+ import { Text as Text$2 } from "./text.js";
9
+ import { withComponentDefaults } from "@monimesl/dot-core";
9
10
  import { useMemo } from "react";
10
11
  import { jsx } from "react/jsx-runtime";
11
12
  //#region src/components/rich-text.tsx
13
+ function themed(name, Component) {
14
+ return function Themed(props) {
15
+ const { components } = useTheme();
16
+ const merged = withComponentDefaults(name, props, components);
17
+ return /* @__PURE__ */ jsx(Component, { ...merged });
18
+ };
19
+ }
20
+ const Image$1 = themed("Image", Image$2);
21
+ const Link$1 = themed("Link", Link$2);
22
+ const Prose$1 = themed("Prose", Prose$2);
23
+ const Text$1 = themed("Text", Text$2);
12
24
  const HEADING_TEXT = {
13
25
  1: { variant: "title" },
14
26
  2: { variant: "subtitle" },
15
27
  3: { weight: "bold" }
16
28
  };
17
- const RichText = ({ markdown }) => {
29
+ const RichText$1 = ({ markdown }) => {
18
30
  const blocks = useMemo(() => parseMarkdown(markdown ?? ""), [markdown]);
19
- return /* @__PURE__ */ jsx(Prose, { children: blocks.map(renderBlock) });
31
+ return /* @__PURE__ */ jsx(Prose$1, { children: blocks.map(renderBlock) });
20
32
  };
21
33
  function renderBlock(block, key) {
22
34
  switch (block.kind) {
23
- case "heading": return /* @__PURE__ */ jsx(Text, {
35
+ case "heading": return /* @__PURE__ */ jsx(Text$1, {
24
36
  ...HEADING_TEXT[block.level],
25
37
  children: block.content.map(renderInline)
26
38
  }, key);
27
- case "paragraph": return /* @__PURE__ */ jsx(Text, { children: block.content.map(renderInline) }, key);
28
- case "list": return /* @__PURE__ */ jsx(BulletList, {
39
+ case "paragraph": return /* @__PURE__ */ jsx(Text$1, { children: block.content.map(renderInline) }, key);
40
+ case "list": return /* @__PURE__ */ jsx(BulletList$1, {
29
41
  ordered: block.ordered,
30
- children: block.items.map((item, itemKey) => /* @__PURE__ */ jsx(Bullet, { children: item.map(renderBlock) }, itemKey))
42
+ children: block.items.map((item, itemKey) => /* @__PURE__ */ jsx(Bullet$1, { children: item.map(renderBlock) }, itemKey))
31
43
  }, key);
32
- case "quote": return /* @__PURE__ */ jsx(Quote, { children: block.blocks.map(renderBlock) }, key);
33
- case "image": return /* @__PURE__ */ jsx(Image, {
44
+ case "quote": return /* @__PURE__ */ jsx(Quote$1, { children: block.blocks.map(renderBlock) }, key);
45
+ case "image": return /* @__PURE__ */ jsx(Image$1, {
34
46
  src: block.src,
35
47
  alt: block.alt
36
48
  }, key);
37
- case "rule": return /* @__PURE__ */ jsx(Divider, {}, key);
49
+ case "rule": return /* @__PURE__ */ jsx(Divider$1, {}, key);
38
50
  }
39
51
  }
40
52
  function renderInline(inline, key) {
41
53
  switch (inline.kind) {
42
54
  case "text": return inline.text;
43
- case "strong": return /* @__PURE__ */ jsx(Text, {
55
+ case "strong": return /* @__PURE__ */ jsx(Text$1, {
44
56
  weight: "bold",
45
57
  children: inline.children.map(renderInline)
46
58
  }, key);
47
- case "emphasis": return /* @__PURE__ */ jsx(Text, {
59
+ case "emphasis": return /* @__PURE__ */ jsx(Text$1, {
48
60
  italic: true,
49
61
  children: inline.children.map(renderInline)
50
62
  }, key);
51
63
  case "code": return /* @__PURE__ */ jsx(Code, { text: inline.text }, key);
52
- case "link": return isHttps(inline.href) ? /* @__PURE__ */ jsx(Link, {
64
+ case "link": return isHttps(inline.href) ? /* @__PURE__ */ jsx(Link$1, {
53
65
  href: inline.href,
54
66
  children: inline.children.map(renderInline)
55
67
  }, key) : inline.children.map(renderInline);
@@ -70,4 +82,4 @@ function Code({ text }) {
70
82
  });
71
83
  }
72
84
  //#endregion
73
- export { RichText };
85
+ export { RichText$1 as RichText };
@@ -1,7 +1,10 @@
1
- import { SPACE } from "./tokens.js";
1
+ import { SCROLL_SHADOW_ROOM, SHADOW_REACH } from "./tokens.js";
2
+ import { useTheme } from "../theme.js";
2
3
  import { paddingStyle } from "./padding.js";
4
+ import { SideRoomContext } from "./side-room.js";
5
+ import { HiddenViewContext } from "./hidden-view.js";
3
6
  import { createEvent } from "@monimesl/dot-core";
4
- import { useEffect, useRef } from "react";
7
+ import { useContext, useEffect, useRef } from "react";
5
8
  import { jsx } from "react/jsx-runtime";
6
9
  //#region src/components/scroll.tsx
7
10
  const REST_DELAY_MS = 120;
@@ -9,11 +12,15 @@ const Scroll$1 = ({ gap = "medium", snap = "none", index, onChange, children, ..
9
12
  const rowRef = useRef(null);
10
13
  const reportedIndex = useRef(void 0);
11
14
  const restTimer = useRef(void 0);
12
- const paddingCss = paddingStyle(padding);
13
- const startPadding = Number(paddingCss.paddingInlineStart);
15
+ const { space, elevation } = useTheme();
16
+ const hidden = useContext(HiddenViewContext);
17
+ const paddingCss = paddingStyle(padding, space);
18
+ const sideRoom = useContext(SideRoomContext) && elevation === "raised" ? SHADOW_REACH.sides : 0;
19
+ const startPadding = Number(paddingCss.paddingInlineStart) + sideRoom;
20
+ const endPadding = Number(paddingCss.paddingInlineEnd) + sideRoom;
14
21
  useEffect(() => {
15
22
  const element = rowRef.current;
16
- if (index === void 0 || index === reportedIndex.current || !element) return;
23
+ if (index === void 0 || index === reportedIndex.current || !element || hidden) return;
17
24
  const child = element.children[index];
18
25
  if (child) {
19
26
  reportedIndex.current = index;
@@ -22,7 +29,11 @@ const Scroll$1 = ({ gap = "medium", snap = "none", index, onChange, children, ..
22
29
  behavior: "smooth"
23
30
  });
24
31
  }
25
- }, [index, startPadding]);
32
+ }, [
33
+ index,
34
+ startPadding,
35
+ hidden
36
+ ]);
26
37
  useEffect(() => {
27
38
  return () => clearTimeout(restTimer.current);
28
39
  }, []);
@@ -43,10 +54,22 @@ const Scroll$1 = ({ gap = "medium", snap = "none", index, onChange, children, ..
43
54
  }, REST_DELAY_MS);
44
55
  } : void 0,
45
56
  style: {
46
- gap: SPACE[gap],
47
- ...paddingCss,
48
- scrollPaddingInlineStart: paddingCss.paddingInlineStart,
49
- scrollPaddingInlineEnd: paddingCss.paddingInlineEnd,
57
+ position: "relative",
58
+ display: "flex",
59
+ overflowX: "auto",
60
+ overflowY: "hidden",
61
+ overscrollBehaviorX: "contain",
62
+ scrollbarWidth: "none",
63
+ gap: space[gap],
64
+ paddingTop: Number(paddingCss.paddingTop) + SCROLL_SHADOW_ROOM.top,
65
+ paddingBottom: Number(paddingCss.paddingBottom) + SCROLL_SHADOW_ROOM.bottom,
66
+ paddingInlineStart: startPadding,
67
+ paddingInlineEnd: endPadding,
68
+ marginTop: -SCROLL_SHADOW_ROOM.top,
69
+ marginBottom: -SCROLL_SHADOW_ROOM.bottom,
70
+ marginInline: -sideRoom,
71
+ scrollPaddingInlineStart: startPadding,
72
+ scrollPaddingInlineEnd: endPadding,
50
73
  scrollSnapType: snap === "none" ? void 0 : "x mandatory",
51
74
  "--dot-scroll-snap": snap === "none" ? "none" : snap
52
75
  },
@@ -1,5 +1,5 @@
1
- import { useTheme } from "../theme.js";
2
1
  import { ICON_SIZE, SPACE } from "./tokens.js";
2
+ import { useTheme } from "../theme.js";
3
3
  import { Field } from "./field.js";
4
4
  import { useFieldBox, useFieldNote } from "./field-box.js";
5
5
  import { CHEVRON_DOWN_ARTWORK } from "./icon-artwork.js";
@@ -1,8 +1,9 @@
1
- import { FONT_FAMILY, useTheme } from "../theme.js";
2
- import { CARD_RADIUS_SCALE, FONT_SIZE, ICON_SIZE, SPACE, WEIGHTS } from "./tokens.js";
1
+ import { CARD_RADIUS_SCALE, ICON_SIZE, SPACE, WEIGHTS } from "./tokens.js";
2
+ import { useTheme } from "../theme.js";
3
3
  import { CLOSE_ARTWORK } from "./icon-artwork.js";
4
4
  import { IconSvg } from "./icon-svg.js";
5
5
  import { pinnedPaddingStyle } from "./padding.js";
6
+ import { HiddenViewContext } from "./hidden-view.js";
6
7
  import { DialogBackdrop } from "../vendor/@base-ui/react/dialog/backdrop/DialogBackdrop.js";
7
8
  import { DialogClose } from "../vendor/@base-ui/react/dialog/close/DialogClose.js";
8
9
  import { DialogPopup } from "../vendor/@base-ui/react/dialog/popup/DialogPopup.js";
@@ -11,14 +12,16 @@ import { DialogRoot } from "../vendor/@base-ui/react/dialog/root/DialogRoot.js";
11
12
  import { DialogTitle } from "../vendor/@base-ui/react/dialog/title/DialogTitle.js";
12
13
  import { usePortalContainer } from "../portal.js";
13
14
  import { createEvent } from "@monimesl/dot-core";
15
+ import { useContext } from "react";
14
16
  import { jsx, jsxs } from "react/jsx-runtime";
15
17
  //#region src/components/sheet.tsx
16
18
  const SheetPanel = ({ open, title, showCloseIcon = false, onClose, children, ...padding }) => {
17
- const { colors, radius } = useTheme();
19
+ const { colors, radius, fontFamily, space, fontSize, headingFontFamily, headingWeight } = useTheme();
18
20
  const container = usePortalContainer();
21
+ const hidden = useContext(HiddenViewContext);
19
22
  const cornerRadius = radius * CARD_RADIUS_SCALE;
20
23
  return /* @__PURE__ */ jsx(DialogRoot, {
21
- open,
24
+ open: open && !hidden,
22
25
  onOpenChange: (next) => {
23
26
  if (!next) onClose();
24
27
  },
@@ -32,7 +35,7 @@ const SheetPanel = ({ open, title, showCloseIcon = false, onClose, children, ...
32
35
  zIndex: 100,
33
36
  background: "rgba(0, 0, 0, 0.4)"
34
37
  }
35
- }), /* @__PURE__ */ jsxs(DialogPopup, {
38
+ }), /* @__PURE__ */ jsx(DialogPopup, {
36
39
  className: "dot-sheet",
37
40
  "aria-label": title,
38
41
  style: {
@@ -40,56 +43,62 @@ const SheetPanel = ({ open, title, showCloseIcon = false, onClose, children, ...
40
43
  insetInline: 0,
41
44
  bottom: 0,
42
45
  zIndex: 101,
43
- display: "flex",
44
- flexDirection: "column",
45
- gap: SPACE.medium,
46
46
  maxHeight: "85vh",
47
47
  overflowY: "auto",
48
- ...pinnedPaddingStyle(padding, {
49
- top: 16,
50
- start: 16,
51
- end: 16,
52
- bottom: 24
53
- }),
54
48
  borderTopLeftRadius: cornerRadius,
55
49
  borderTopRightRadius: cornerRadius,
56
50
  background: colors.surface,
57
51
  color: colors.text,
58
- fontFamily: FONT_FAMILY,
52
+ fontFamily,
59
53
  outline: "none"
60
54
  },
61
- children: [
62
- title ? /* @__PURE__ */ jsx(DialogTitle, {
63
- style: {
64
- margin: 0,
65
- fontSize: FONT_SIZE.body,
66
- fontWeight: WEIGHTS.bold,
67
- lineHeight: "normal",
68
- textAlign: "center"
69
- },
70
- children: title
71
- }) : null,
72
- showCloseIcon ? /* @__PURE__ */ jsx(DialogClose, {
73
- "aria-label": "Close",
74
- style: {
75
- position: "absolute",
76
- top: 10,
77
- insetInlineEnd: 10,
78
- display: "flex",
79
- padding: 4,
80
- border: "none",
81
- borderRadius: "50%",
82
- background: "transparent",
83
- cursor: "pointer"
84
- },
85
- children: /* @__PURE__ */ jsx(IconSvg, {
86
- artwork: CLOSE_ARTWORK,
87
- size: ICON_SIZE.medium,
88
- color: colors.subtle
55
+ children: /* @__PURE__ */ jsxs("div", {
56
+ style: {
57
+ display: "flex",
58
+ flexDirection: "column",
59
+ gap: SPACE.medium,
60
+ overflow: "clip",
61
+ ...pinnedPaddingStyle(padding, space, {
62
+ top: 16,
63
+ start: 16,
64
+ end: 16,
65
+ bottom: 24
89
66
  })
90
- }) : null,
91
- children
92
- ]
67
+ },
68
+ children: [
69
+ title ? /* @__PURE__ */ jsx(DialogTitle, {
70
+ style: {
71
+ margin: 0,
72
+ fontSize: fontSize.body,
73
+ fontFamily: headingFontFamily,
74
+ fontWeight: WEIGHTS[headingWeight ?? "bold"],
75
+ lineHeight: "normal",
76
+ textAlign: "center"
77
+ },
78
+ children: title
79
+ }) : null,
80
+ showCloseIcon ? /* @__PURE__ */ jsx(DialogClose, {
81
+ "aria-label": "Close",
82
+ style: {
83
+ position: "absolute",
84
+ top: 10,
85
+ insetInlineEnd: 10,
86
+ display: "flex",
87
+ padding: 4,
88
+ border: "none",
89
+ borderRadius: "50%",
90
+ background: "transparent",
91
+ cursor: "pointer"
92
+ },
93
+ children: /* @__PURE__ */ jsx(IconSvg, {
94
+ artwork: CLOSE_ARTWORK,
95
+ size: ICON_SIZE.medium,
96
+ color: colors.subtle
97
+ })
98
+ }) : null,
99
+ children
100
+ ]
101
+ })
93
102
  })]
94
103
  })
95
104
  });
@@ -0,0 +1,5 @@
1
+ import { createContext } from "react";
2
+ //#region src/components/side-room.ts
3
+ const SideRoomContext = createContext(true);
4
+ //#endregion
5
+ export { SideRoomContext };
@@ -1,5 +1,5 @@
1
- import { useTheme } from "../theme.js";
2
1
  import { SPACE } from "./tokens.js";
2
+ import { useTheme } from "../theme.js";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  //#region src/components/skeleton.tsx
5
5
  const LINE_HEIGHT = 12;
@@ -1,5 +1,5 @@
1
+ import { DISABLED_OPACITY } from "./tokens.js";
1
2
  import { useTheme } from "../theme.js";
2
- import { DISABLED_OPACITY, FONT_SIZE } from "./tokens.js";
3
3
  import { Field, FieldLabel } from "./field.js";
4
4
  import { useFieldNote } from "./field-box.js";
5
5
  import { useTypedText } from "./typed-text.js";
@@ -7,7 +7,7 @@ import { createEvent } from "@monimesl/dot-core";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
8
  //#region src/components/slider.tsx
9
9
  const Slider$1 = ({ value, min = 0, max = 100, step = 1, showValue, label, hint, disabled, onChange }) => {
10
- const { colors } = useTheme();
10
+ const { colors, fontSize } = useTheme();
11
11
  const [positionText, showPosition] = useTypedText(value === void 0 ? void 0 : String(value), onChange !== void 0);
12
12
  const { noteId, controlAttributes } = useFieldNote(hint, void 0);
13
13
  const shownValue = positionText === "" ? String(min) : positionText;
@@ -23,7 +23,7 @@ const Slider$1 = ({ value, min = 0, max = 100, step = 1, showValue, label, hint,
23
23
  },
24
24
  children: [/* @__PURE__ */ jsx(FieldLabel, { children: label }), showValue ? /* @__PURE__ */ jsx("span", {
25
25
  style: {
26
- fontSize: FONT_SIZE.caption,
26
+ fontSize: fontSize.caption,
27
27
  color: colors.subtle,
28
28
  fontVariantNumeric: "tabular-nums"
29
29
  },
@@ -1,5 +1,5 @@
1
- import { useTheme } from "../theme.js";
2
1
  import { ICON_SIZE } from "./tokens.js";
2
+ import { useTheme } from "../theme.js";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  //#region src/components/spinner.tsx
5
5
  function LoadingIcon({ size }) {
@@ -1,4 +1,5 @@
1
1
  import { useTheme } from "../theme.js";
2
+ import { SideRoomContext } from "./side-room.js";
2
3
  import { boxStyle } from "./box.js";
3
4
  import { Children } from "react";
4
5
  import { jsx } from "react/jsx-runtime";
@@ -11,14 +12,17 @@ const Stack = (props) => {
11
12
  display: "grid",
12
13
  ...boxStyle(props, theme)
13
14
  },
14
- children: Children.map(props.children, (child) => /* @__PURE__ */ jsx("div", {
15
- style: {
16
- gridArea: "1 / 1",
17
- display: "grid",
18
- minWidth: 0
19
- },
20
- children: child
21
- }))
15
+ children: /* @__PURE__ */ jsx(SideRoomContext.Provider, {
16
+ value: false,
17
+ children: Children.map(props.children, (child) => /* @__PURE__ */ jsx("div", {
18
+ style: {
19
+ gridArea: "1 / 1",
20
+ display: "grid",
21
+ minWidth: 0
22
+ },
23
+ children: child
24
+ }))
25
+ })
22
26
  });
23
27
  };
24
28
  //#endregion
@@ -1,5 +1,5 @@
1
+ import { CENTERED, ICON_SIZE, WEIGHTS, pressLook } from "./tokens.js";
1
2
  import { useTheme } from "../theme.js";
2
- import { CENTERED, DISABLED_OPACITY, FONT_SIZE, ICON_SIZE, WEIGHTS } from "./tokens.js";
3
3
  import { Field } from "./field.js";
4
4
  import { useFieldNote } from "./field-box.js";
5
5
  import { useTypedText } from "./typed-text.js";
@@ -8,7 +8,7 @@ import { createEvent } from "@monimesl/dot-core";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  //#region src/components/stepper.tsx
10
10
  const Stepper$1 = ({ value, min, max, step = 1, label, hint, disabled, onChange }) => {
11
- const { colors } = useTheme();
11
+ const { colors, fontSize } = useTheme();
12
12
  const [shownText, showText] = useTypedText(value === void 0 ? void 0 : String(value), onChange !== void 0);
13
13
  const { noteId, controlAttributes } = useFieldNote(hint, void 0);
14
14
  const current = shownText === "" ? min ?? 0 : Number(shownText);
@@ -46,7 +46,7 @@ const Stepper$1 = ({ value, min, max, step = 1, label, hint, disabled, onChange
46
46
  style: {
47
47
  minWidth: 32,
48
48
  textAlign: "center",
49
- fontSize: FONT_SIZE.subtitle,
49
+ fontSize: fontSize.subtitle,
50
50
  fontWeight: WEIGHTS.bold,
51
51
  fontVariantNumeric: "tabular-nums",
52
52
  color: colors.text
@@ -78,8 +78,7 @@ function StepButton({ icon, label, disabled, onPress }) {
78
78
  borderRadius: radius,
79
79
  background: colors.muted,
80
80
  color: colors.text,
81
- opacity: disabled ? DISABLED_OPACITY : 1,
82
- cursor: disabled ? "default" : "pointer"
81
+ ...pressLook(disabled)
83
82
  },
84
83
  children: /* @__PURE__ */ jsx(IconGraphic, {
85
84
  name: icon,
@@ -1,20 +1,23 @@
1
+ import { CENTERED, WEIGHTS } from "./tokens.js";
1
2
  import { useTheme } from "../theme.js";
2
- import { CENTERED, FONT_SIZE, WEIGHTS } from "./tokens.js";
3
3
  import { paddingStyle } from "./padding.js";
4
4
  import { IconGraphic } from "./icon.js";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/components/steps.tsx
7
7
  const MARK_SIZE = 24;
8
- const Steps = ({ children, ...padding }) => /* @__PURE__ */ jsx("ol", {
9
- className: "dot-steps",
10
- style: {
11
- display: "flex",
12
- flexDirection: "column",
13
- margin: 0,
14
- ...paddingStyle(padding)
15
- },
16
- children
17
- });
8
+ const Steps = ({ children, ...padding }) => {
9
+ const { space } = useTheme();
10
+ return /* @__PURE__ */ jsx("ol", {
11
+ className: "dot-steps",
12
+ style: {
13
+ display: "flex",
14
+ flexDirection: "column",
15
+ margin: 0,
16
+ ...paddingStyle(padding, space)
17
+ },
18
+ children
19
+ });
20
+ };
18
21
  function stepMark(colors, status) {
19
22
  switch (status) {
20
23
  case "done": return {
@@ -40,7 +43,7 @@ function stepMark(colors, status) {
40
43
  }
41
44
  }
42
45
  const Step = ({ title, text, status = "upcoming" }) => {
43
- const { colors } = useTheme();
46
+ const { colors, fontSize } = useTheme();
44
47
  const { background, border, icon } = stepMark(colors, status);
45
48
  return /* @__PURE__ */ jsxs("li", {
46
49
  className: "dot-step",
@@ -90,7 +93,7 @@ const Step = ({ title, text, status = "upcoming" }) => {
90
93
  },
91
94
  children: [/* @__PURE__ */ jsx("span", {
92
95
  style: {
93
- fontSize: FONT_SIZE.body,
96
+ fontSize: fontSize.body,
94
97
  fontWeight: status === "current" ? WEIGHTS.bold : WEIGHTS.medium,
95
98
  color: status === "upcoming" ? colors.subtle : colors.text,
96
99
  lineHeight: `${MARK_SIZE}px`
@@ -98,7 +101,7 @@ const Step = ({ title, text, status = "upcoming" }) => {
98
101
  children: title
99
102
  }), text ? /* @__PURE__ */ jsx("span", {
100
103
  style: {
101
- fontSize: FONT_SIZE.caption,
104
+ fontSize: fontSize.caption,
102
105
  color: colors.subtle
103
106
  },
104
107
  children: text
@@ -1,94 +1,141 @@
1
+ import { CENTERED, ICON_SIZE, PILL_STYLE, WEIGHTS, pressLook } from "./tokens.js";
1
2
  import { useTheme } from "../theme.js";
2
- import { CENTERED, FONT_SIZE, PILL_STYLE, WEIGHTS } from "./tokens.js";
3
3
  import { paddingStyle } from "./padding.js";
4
+ import { IconGraphic } from "./icon.js";
4
5
  import { TabsRoot } from "../vendor/@base-ui/react/tabs/root/TabsRoot.js";
5
6
  import { TabsTab } from "../vendor/@base-ui/react/tabs/tab/TabsTab.js";
6
7
  import { TabsList } from "../vendor/@base-ui/react/tabs/list/TabsList.js";
7
- import { createEvent } from "@monimesl/dot-core";
8
+ import { DEFAULT_VARIANTS, createEvent } from "@monimesl/dot-core";
8
9
  import { createContext, useContext } from "react";
9
10
  import { jsx, jsxs } from "react/jsx-runtime";
10
11
  //#region src/components/tabs.tsx
11
12
  const TabsContext = createContext({
12
13
  value: void 0,
13
- segmented: false
14
+ variant: DEFAULT_VARIANTS.Tabs
14
15
  });
15
- const Tabs$1 = ({ value, variant = "underline", onChange, children, ...padding }) => {
16
- const { colors, radius } = useTheme();
17
- const segmented = variant === "segmented";
18
- let variantStyle;
19
- if (segmented) variantStyle = {
16
+ const BAR_ICON_SIZE = 24;
17
+ const Tabs$1 = ({ value, variant = DEFAULT_VARIANTS.Tabs, onChange, children, ...padding }) => {
18
+ const { colors, radius, space } = useTheme();
19
+ let variantStyle = {};
20
+ if (variant === "segmented") variantStyle = {
20
21
  gap: 2,
21
22
  padding: 3,
22
23
  borderRadius: radius,
23
24
  background: colors.muted
24
25
  };
25
- else variantStyle = { borderBottom: `1px solid ${colors.border}` };
26
+ else if (variant === "underline") variantStyle = { boxShadow: `inset 0 -1px 0 ${colors.border}` };
26
27
  return /* @__PURE__ */ jsx(TabsRoot, {
27
28
  value: value ?? null,
28
29
  onValueChange: (next) => {
29
30
  if (next !== null && next !== value) onChange?.(createEvent("change", { value: next }));
30
31
  },
31
- style: paddingStyle(padding),
32
+ style: paddingStyle(padding, space),
32
33
  children: /* @__PURE__ */ jsx(TabsList, {
33
34
  className: "dot-tabs",
34
35
  style: {
35
36
  display: "flex",
36
37
  overflowX: "auto",
38
+ overflowY: "hidden",
37
39
  ...variantStyle
38
40
  },
39
41
  children: /* @__PURE__ */ jsx(TabsContext.Provider, {
40
42
  value: {
41
43
  value,
42
- segmented
44
+ variant
43
45
  },
44
46
  children
45
47
  })
46
48
  })
47
49
  });
48
50
  };
49
- const Tab$1 = ({ value, label, badge }) => {
50
- const { colors, radius } = useTheme();
51
- const { value: chosen, segmented } = useContext(TabsContext);
51
+ const Tab$1 = ({ value, label, icon, badge, disabled }) => {
52
+ const { colors, radius, fontSize } = useTheme();
53
+ const { value: chosen, variant } = useContext(TabsContext);
52
54
  if (value === void 0) return null;
53
55
  const selected = value === chosen;
56
+ const bar = variant === "bar";
54
57
  let color = colors.subtle;
55
- if (selected) color = segmented ? colors.text : colors.primary;
58
+ if (selected) color = variant === "segmented" ? colors.text : colors.primaryText;
56
59
  let variantStyle;
57
- if (segmented) variantStyle = {
60
+ if (variant === "segmented") variantStyle = {
61
+ minHeight: 36,
58
62
  borderRadius: Math.max(radius - 2, 0),
59
63
  background: selected ? colors.surface : "transparent",
60
64
  boxShadow: selected ? "0 1px 3px rgba(0, 0, 0, 0.15)" : "none"
61
65
  };
66
+ else if (bar) variantStyle = {
67
+ flexDirection: "column",
68
+ gap: 2,
69
+ flex: "1 1 0",
70
+ minWidth: 0,
71
+ minHeight: 50,
72
+ padding: "6px 4px",
73
+ fontSize: fontSize.caption,
74
+ background: "transparent"
75
+ };
62
76
  else variantStyle = {
63
- marginBottom: -1,
77
+ minHeight: 44,
64
78
  background: "transparent",
65
- borderBottom: `2px solid ${selected ? colors.primary : "transparent"}`
79
+ boxShadow: selected ? `inset 0 -2px 0 ${colors.primary}` : "none"
66
80
  };
81
+ const count = badge ? /* @__PURE__ */ jsx("span", {
82
+ style: {
83
+ ...PILL_STYLE,
84
+ display: "block",
85
+ background: colors.primary,
86
+ color: colors.onPrimary
87
+ },
88
+ children: badge
89
+ }) : null;
90
+ const countOnIcon = bar && Boolean(icon);
67
91
  return /* @__PURE__ */ jsxs(TabsTab, {
68
92
  className: "dot-tab",
69
93
  value,
94
+ disabled,
70
95
  style: {
71
96
  ...CENTERED,
72
97
  gap: 6,
73
98
  flex: "1 0 auto",
74
- minHeight: segmented ? 36 : 44,
75
99
  padding: "0 12px",
76
100
  border: "none",
77
- fontSize: FONT_SIZE.body,
101
+ fontSize: fontSize.body,
78
102
  fontWeight: selected ? WEIGHTS.bold : WEIGHTS.medium,
79
103
  whiteSpace: "nowrap",
80
104
  color,
81
- cursor: "pointer",
105
+ ...pressLook(disabled),
82
106
  ...variantStyle
83
107
  },
84
- children: [label, badge ? /* @__PURE__ */ jsx("span", {
108
+ children: [icon ? /* @__PURE__ */ jsxs("span", {
85
109
  style: {
86
- ...PILL_STYLE,
87
- background: colors.primary,
88
- color: colors.onPrimary
110
+ position: "relative",
111
+ display: "inline-flex"
89
112
  },
90
- children: badge
91
- }) : null]
113
+ children: [/* @__PURE__ */ jsx(IconGraphic, {
114
+ name: icon,
115
+ size: bar ? BAR_ICON_SIZE : ICON_SIZE.medium,
116
+ color: "currentColor"
117
+ }), countOnIcon && count ? /* @__PURE__ */ jsx("span", {
118
+ style: {
119
+ position: "absolute",
120
+ top: -6,
121
+ insetInlineStart: 16
122
+ },
123
+ children: count
124
+ }) : null]
125
+ }) : null, /* @__PURE__ */ jsxs("span", {
126
+ style: {
127
+ ...CENTERED,
128
+ gap: 6,
129
+ maxWidth: "100%"
130
+ },
131
+ children: [/* @__PURE__ */ jsx("span", {
132
+ style: {
133
+ overflow: "hidden",
134
+ textOverflow: "ellipsis"
135
+ },
136
+ children: label
137
+ }), countOnIcon ? null : count]
138
+ })]
92
139
  });
93
140
  };
94
141
  //#endregion