@monimesl/dot-renderer-react 1.0.0-beta.7 → 1.0.0-beta.8

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 (43) hide show
  1. package/dist/components/amount-input.js +1 -1
  2. package/dist/components/avatar.js +1 -1
  3. package/dist/components/box.js +8 -2
  4. package/dist/components/button.js +64 -14
  5. package/dist/components/carousel.js +4 -4
  6. package/dist/components/chip.js +3 -3
  7. package/dist/components/code-input.js +1 -1
  8. package/dist/components/detail-row.js +5 -5
  9. package/dist/components/disclosure.js +4 -4
  10. package/dist/components/empty-state.js +7 -6
  11. package/dist/components/feedback.js +7 -7
  12. package/dist/components/field-box.js +1 -1
  13. package/dist/components/field.js +5 -4
  14. package/dist/components/footer.js +3 -3
  15. package/dist/components/grid.js +16 -13
  16. package/dist/components/icon-button.js +1 -1
  17. package/dist/components/icon.js +32 -5
  18. package/dist/components/input.js +1 -1
  19. package/dist/components/list.js +10 -8
  20. package/dist/components/option.js +3 -3
  21. package/dist/components/padding.js +9 -10
  22. package/dist/components/prose.js +23 -20
  23. package/dist/components/scroll.js +4 -3
  24. package/dist/components/select.js +1 -1
  25. package/dist/components/sheet.js +8 -7
  26. package/dist/components/skeleton.js +1 -1
  27. package/dist/components/slider.js +3 -3
  28. package/dist/components/spinner.js +1 -1
  29. package/dist/components/stepper.js +3 -3
  30. package/dist/components/steps.js +17 -14
  31. package/dist/components/tabs.js +7 -7
  32. package/dist/components/text.js +10 -14
  33. package/dist/components/toast.js +3 -3
  34. package/dist/components/toggles.js +13 -9
  35. package/dist/components/tokens.d.ts +16 -0
  36. package/dist/components/tokens.js +11 -1
  37. package/dist/components/view.js +16 -7
  38. package/dist/page-root.js +9 -3
  39. package/dist/pull-to-refresh.js +1 -1
  40. package/dist/root.js +3 -3
  41. package/dist/theme.d.ts +11 -1
  42. package/dist/theme.js +80 -14
  43. package/package.json +4 -4
@@ -1,4 +1,3 @@
1
- import { SPACE } from "./tokens.js";
2
1
  //#region src/components/padding.ts
3
2
  const NO_INSETS = {
4
3
  top: 0,
@@ -14,21 +13,21 @@ function insets(block, inline = block) {
14
13
  bottom: block
15
14
  };
16
15
  }
17
- function paddingStyle(props, ownInsets = NO_INSETS) {
16
+ function paddingStyle(props, space, ownInsets = NO_INSETS) {
18
17
  return {
19
- paddingTop: sidePadding(props.paddingTop ?? props.padding, ownInsets.top),
20
- paddingInlineStart: sidePadding(props.paddingStart ?? props.padding, ownInsets.start),
21
- paddingInlineEnd: sidePadding(props.paddingEnd ?? props.padding, ownInsets.end),
22
- paddingBottom: sidePadding(props.paddingBottom ?? props.padding, ownInsets.bottom)
18
+ paddingTop: sidePadding(props.paddingTop ?? props.padding, space, ownInsets.top),
19
+ paddingInlineStart: sidePadding(props.paddingStart ?? props.padding, space, ownInsets.start),
20
+ paddingInlineEnd: sidePadding(props.paddingEnd ?? props.padding, space, ownInsets.end),
21
+ paddingBottom: sidePadding(props.paddingBottom ?? props.padding, space, ownInsets.bottom)
23
22
  };
24
23
  }
25
- function sidePadding(pageSpace, ownPixels) {
24
+ function sidePadding(pageSpace, space, ownPixels) {
26
25
  if (pageSpace === void 0) return ownPixels;
27
- return SPACE[pageSpace];
26
+ return space[pageSpace];
28
27
  }
29
28
  const HOME_INDICATOR = "env(safe-area-inset-bottom, 0px)";
30
- function pinnedPaddingStyle(props, ownInsets) {
31
- const style = paddingStyle(props, ownInsets);
29
+ function pinnedPaddingStyle(props, space, ownInsets) {
30
+ const style = paddingStyle(props, space, ownInsets);
32
31
  return {
33
32
  ...style,
34
33
  paddingBottom: `calc(${style.paddingBottom}px + ${HOME_INDICATOR})`
@@ -1,29 +1,32 @@
1
+ import { SELECTABLE } from "./tokens.js";
1
2
  import { useTheme } from "../theme.js";
2
- import { FONT_SIZE, SELECTABLE } from "./tokens.js";
3
3
  import { paddingStyle } from "./padding.js";
4
4
  import { InsideProse } from "./prose-context.js";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/components/prose.tsx
7
7
  const READING_WIDTH = 680;
8
- const Prose = ({ children, ...padding }) => /* @__PURE__ */ jsx("div", {
9
- className: "dot-prose",
10
- style: {
11
- display: "flex",
12
- flexDirection: "column",
13
- gap: 12,
14
- width: "100%",
15
- maxWidth: READING_WIDTH,
16
- marginInline: "auto",
17
- ...SELECTABLE,
18
- ...paddingStyle(padding)
19
- },
20
- children: /* @__PURE__ */ jsx(InsideProse.Provider, {
21
- value: true,
22
- children
23
- })
24
- });
8
+ const Prose = ({ children, ...padding }) => {
9
+ const { space } = useTheme();
10
+ return /* @__PURE__ */ jsx("div", {
11
+ className: "dot-prose",
12
+ style: {
13
+ display: "flex",
14
+ flexDirection: "column",
15
+ gap: 12,
16
+ width: "100%",
17
+ maxWidth: READING_WIDTH,
18
+ marginInline: "auto",
19
+ ...SELECTABLE,
20
+ ...paddingStyle(padding, space)
21
+ },
22
+ children: /* @__PURE__ */ jsx(InsideProse.Provider, {
23
+ value: true,
24
+ children
25
+ })
26
+ });
27
+ };
25
28
  const Quote = ({ cite, children }) => {
26
- const { colors } = useTheme();
29
+ const { colors, fontSize } = useTheme();
27
30
  return /* @__PURE__ */ jsxs("blockquote", {
28
31
  className: "dot-quote",
29
32
  style: {
@@ -37,7 +40,7 @@ const Quote = ({ cite, children }) => {
37
40
  },
38
41
  children: [children, cite && /* @__PURE__ */ jsxs("span", {
39
42
  style: {
40
- fontSize: FONT_SIZE.caption,
43
+ fontSize: fontSize.caption,
41
44
  fontStyle: "normal",
42
45
  color: colors.subtle
43
46
  },
@@ -1,4 +1,4 @@
1
- import { SPACE } from "./tokens.js";
1
+ import { useTheme } from "../theme.js";
2
2
  import { paddingStyle } from "./padding.js";
3
3
  import { createEvent } from "@monimesl/dot-core";
4
4
  import { useEffect, useRef } from "react";
@@ -9,7 +9,8 @@ const Scroll$1 = ({ gap = "medium", snap = "none", index, onChange, children, ..
9
9
  const rowRef = useRef(null);
10
10
  const reportedIndex = useRef(void 0);
11
11
  const restTimer = useRef(void 0);
12
- const paddingCss = paddingStyle(padding);
12
+ const { space } = useTheme();
13
+ const paddingCss = paddingStyle(padding, space);
13
14
  const startPadding = Number(paddingCss.paddingInlineStart);
14
15
  useEffect(() => {
15
16
  const element = rowRef.current;
@@ -43,7 +44,7 @@ const Scroll$1 = ({ gap = "medium", snap = "none", index, onChange, children, ..
43
44
  }, REST_DELAY_MS);
44
45
  } : void 0,
45
46
  style: {
46
- gap: SPACE[gap],
47
+ gap: space[gap],
47
48
  ...paddingCss,
48
49
  scrollPaddingInlineStart: paddingCss.paddingInlineStart,
49
50
  scrollPaddingInlineEnd: paddingCss.paddingInlineEnd,
@@ -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,5 +1,5 @@
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";
@@ -14,7 +14,7 @@ import { createEvent } from "@monimesl/dot-core";
14
14
  import { jsx, jsxs } from "react/jsx-runtime";
15
15
  //#region src/components/sheet.tsx
16
16
  const SheetPanel = ({ open, title, showCloseIcon = false, onClose, children, ...padding }) => {
17
- const { colors, radius } = useTheme();
17
+ const { colors, radius, fontFamily, space, fontSize, headingFontFamily, headingWeight } = useTheme();
18
18
  const container = usePortalContainer();
19
19
  const cornerRadius = radius * CARD_RADIUS_SCALE;
20
20
  return /* @__PURE__ */ jsx(DialogRoot, {
@@ -45,7 +45,7 @@ const SheetPanel = ({ open, title, showCloseIcon = false, onClose, children, ...
45
45
  gap: SPACE.medium,
46
46
  maxHeight: "85vh",
47
47
  overflowY: "auto",
48
- ...pinnedPaddingStyle(padding, {
48
+ ...pinnedPaddingStyle(padding, space, {
49
49
  top: 16,
50
50
  start: 16,
51
51
  end: 16,
@@ -55,15 +55,16 @@ const SheetPanel = ({ open, title, showCloseIcon = false, onClose, children, ...
55
55
  borderTopRightRadius: cornerRadius,
56
56
  background: colors.surface,
57
57
  color: colors.text,
58
- fontFamily: FONT_FAMILY,
58
+ fontFamily,
59
59
  outline: "none"
60
60
  },
61
61
  children: [
62
62
  title ? /* @__PURE__ */ jsx(DialogTitle, {
63
63
  style: {
64
64
  margin: 0,
65
- fontSize: FONT_SIZE.body,
66
- fontWeight: WEIGHTS.bold,
65
+ fontSize: fontSize.body,
66
+ fontFamily: headingFontFamily,
67
+ fontWeight: WEIGHTS[headingWeight ?? "bold"],
67
68
  lineHeight: "normal",
68
69
  textAlign: "center"
69
70
  },
@@ -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,5 +1,5 @@
1
+ import { CENTERED, DISABLED_OPACITY, ICON_SIZE, WEIGHTS } 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
@@ -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,10 +1,10 @@
1
+ import { CENTERED, PILL_STYLE, WEIGHTS } 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
4
  import { TabsRoot } from "../vendor/@base-ui/react/tabs/root/TabsRoot.js";
5
5
  import { TabsTab } from "../vendor/@base-ui/react/tabs/tab/TabsTab.js";
6
6
  import { TabsList } from "../vendor/@base-ui/react/tabs/list/TabsList.js";
7
- import { createEvent } from "@monimesl/dot-core";
7
+ import { DEFAULT_VARIANTS, createEvent } from "@monimesl/dot-core";
8
8
  import { createContext, useContext } from "react";
9
9
  import { jsx, jsxs } from "react/jsx-runtime";
10
10
  //#region src/components/tabs.tsx
@@ -12,8 +12,8 @@ const TabsContext = createContext({
12
12
  value: void 0,
13
13
  segmented: false
14
14
  });
15
- const Tabs$1 = ({ value, variant = "underline", onChange, children, ...padding }) => {
16
- const { colors, radius } = useTheme();
15
+ const Tabs$1 = ({ value, variant = DEFAULT_VARIANTS.Tabs, onChange, children, ...padding }) => {
16
+ const { colors, radius, space } = useTheme();
17
17
  const segmented = variant === "segmented";
18
18
  let variantStyle;
19
19
  if (segmented) variantStyle = {
@@ -28,7 +28,7 @@ const Tabs$1 = ({ value, variant = "underline", onChange, children, ...padding }
28
28
  onValueChange: (next) => {
29
29
  if (next !== null && next !== value) onChange?.(createEvent("change", { value: next }));
30
30
  },
31
- style: paddingStyle(padding),
31
+ style: paddingStyle(padding, space),
32
32
  children: /* @__PURE__ */ jsx(TabsList, {
33
33
  className: "dot-tabs",
34
34
  style: {
@@ -47,7 +47,7 @@ const Tabs$1 = ({ value, variant = "underline", onChange, children, ...padding }
47
47
  });
48
48
  };
49
49
  const Tab$1 = ({ value, label, badge }) => {
50
- const { colors, radius } = useTheme();
50
+ const { colors, radius, fontSize } = useTheme();
51
51
  const { value: chosen, segmented } = useContext(TabsContext);
52
52
  if (value === void 0) return null;
53
53
  const selected = value === chosen;
@@ -74,7 +74,7 @@ const Tab$1 = ({ value, label, badge }) => {
74
74
  minHeight: segmented ? 36 : 44,
75
75
  padding: "0 12px",
76
76
  border: "none",
77
- fontSize: FONT_SIZE.body,
77
+ fontSize: fontSize.body,
78
78
  fontWeight: selected ? WEIGHTS.bold : WEIGHTS.medium,
79
79
  whiteSpace: "nowrap",
80
80
  color,
@@ -1,9 +1,9 @@
1
+ import { SELECTABLE, WEIGHTS } from "./tokens.js";
1
2
  import { useTheme } from "../theme.js";
2
- import { FONT_SIZE, SELECTABLE, WEIGHTS } from "./tokens.js";
3
3
  import { paddingStyle } from "./padding.js";
4
- import { isTone, toneColor } from "./tones.js";
4
+ import { textToneColor } from "./box.js";
5
5
  import { InsideProse } from "./prose-context.js";
6
- import { customColor } from "./box.js";
6
+ import { DEFAULT_VARIANTS } from "@monimesl/dot-core";
7
7
  import { createContext, useContext } from "react";
8
8
  import { jsx } from "react/jsx-runtime";
9
9
  //#region src/components/text.tsx
@@ -50,7 +50,7 @@ const DECORATION = {
50
50
  underline: "underline",
51
51
  strikethrough: "line-through"
52
52
  };
53
- const Text = ({ variant = "body", tone, weight, align, maxLines, decoration, numeric, leading, italic, selectable, children, ...padding }) => {
53
+ const Text$1 = ({ variant = DEFAULT_VARIANTS.Text, tone, weight, align, maxLines, decoration, numeric, leading, italic, selectable, children, ...padding }) => {
54
54
  const theme = useTheme();
55
55
  const insideText = useContext(InsideText);
56
56
  const inProse = useContext(InsideProse);
@@ -61,16 +61,17 @@ const Text = ({ variant = "body", tone, weight, align, maxLines, decoration, num
61
61
  marginInline: 0,
62
62
  marginBlockEnd: 0,
63
63
  marginBlockStart: inProse && heading ? void 0 : 0,
64
- fontSize: FONT_SIZE[variant],
65
- fontWeight: WEIGHTS[weight ?? defaultWeight],
64
+ fontSize: theme.fontSize[variant],
65
+ fontFamily: heading ? theme.headingFontFamily : void 0,
66
+ fontWeight: WEIGHTS[weight ?? (heading ? theme.headingWeight : void 0) ?? defaultWeight],
66
67
  fontStyle: italic ? "italic" : void 0,
67
68
  letterSpacing: variant === "display" ? "-0.02em" : "normal",
68
- color: tone ? textColor(tone, theme) : "inherit",
69
+ color: tone ? textToneColor(tone, theme) : "inherit",
69
70
  textAlign: align,
70
71
  textDecorationLine: decoration ? DECORATION[decoration] : void 0,
71
72
  fontVariantNumeric: numeric ? "tabular-nums" : void 0,
72
73
  ...selectable ? SELECTABLE : void 0,
73
- ...paddingStyle(padding)
74
+ ...paddingStyle(padding, theme.space)
74
75
  };
75
76
  if (!insideText) {
76
77
  style.lineHeight = lineHeight + LEADING_CHANGE[leading ?? defaultLeading];
@@ -98,10 +99,5 @@ const Text = ({ variant = "body", tone, weight, align, maxLines, decoration, num
98
99
  children: content
99
100
  });
100
101
  };
101
- function textColor(tone, theme) {
102
- if (isTone(tone)) return toneColor(theme.colors, tone);
103
- if (tone === "onPrimary") return theme.colors.onPrimary;
104
- return customColor(tone, theme);
105
- }
106
102
  //#endregion
107
- export { Text };
103
+ export { Text$1 as Text };
@@ -1,5 +1,5 @@
1
+ import { ICON_SIZE, SPACE } from "./tokens.js";
1
2
  import { useTheme } from "../theme.js";
2
- import { FONT_SIZE, ICON_SIZE, SPACE } from "./tokens.js";
3
3
  import { IconSvg } from "./icon-svg.js";
4
4
  import { STATUS_ARTWORK } from "./tones.js";
5
5
  import { createEvent } from "@monimesl/dot-core";
@@ -7,7 +7,7 @@ import { useEffect, useEffectEvent, useState } from "react";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
8
  //#region src/components/toast.tsx
9
9
  const Toast$1 = ({ message, tone = "default", duration = 2500, onHide }) => {
10
- const { colors, radius } = useTheme();
10
+ const { colors, radius, fontSize } = useTheme();
11
11
  const [hidden, setHidden] = useState(false);
12
12
  const [previousMessage, setPreviousMessage] = useState(message);
13
13
  if (message !== previousMessage) {
@@ -42,7 +42,7 @@ const Toast$1 = ({ message, tone = "default", duration = 2500, onHide }) => {
42
42
  borderRadius: radius,
43
43
  background: colors.primary,
44
44
  color: colors.onPrimary,
45
- fontSize: FONT_SIZE.body,
45
+ fontSize: fontSize.body,
46
46
  boxShadow: "0 4px 16px rgba(0, 0, 0, 0.2)"
47
47
  },
48
48
  children: [tone === "default" ? null : /* @__PURE__ */ jsx(IconSvg, {
@@ -1,5 +1,5 @@
1
+ import { CENTERED, DISABLED_OPACITY, ICON_SIZE, SPACE } from "./tokens.js";
1
2
  import { useTheme } from "../theme.js";
2
- import { CENTERED, DISABLED_OPACITY, FONT_SIZE, ICON_SIZE, SPACE } from "./tokens.js";
3
3
  import { FieldLabel } from "./field.js";
4
4
  import { CHECK_ARTWORK } from "./icon-artwork.js";
5
5
  import { IconSvg } from "./icon-svg.js";
@@ -14,7 +14,8 @@ import { createEvent } from "@monimesl/dot-core";
14
14
  import { useId } from "react";
15
15
  import { jsx, jsxs } from "react/jsx-runtime";
16
16
  //#region src/components/toggles.tsx
17
- function rowStyle(colors, disabled) {
17
+ function rowStyle(theme, disabled) {
18
+ const { colors, fontSize } = theme;
18
19
  return {
19
20
  display: "flex",
20
21
  alignItems: "center",
@@ -24,7 +25,7 @@ function rowStyle(colors, disabled) {
24
25
  border: "none",
25
26
  background: "transparent",
26
27
  color: colors.text,
27
- fontSize: FONT_SIZE.body,
28
+ fontSize: fontSize.body,
28
29
  textAlign: "start",
29
30
  opacity: disabled ? DISABLED_OPACITY : 1,
30
31
  cursor: disabled ? "default" : "pointer"
@@ -47,14 +48,15 @@ function ChoiceMark({ round, checked, children }) {
47
48
  });
48
49
  }
49
50
  const Switch$1 = ({ checked = false, label, disabled, onChange }) => {
50
- const { colors } = useTheme();
51
+ const theme = useTheme();
52
+ const { colors } = theme;
51
53
  return /* @__PURE__ */ jsxs(SwitchRoot, {
52
54
  className: "dot-switch",
53
55
  checked,
54
56
  disabled,
55
57
  onCheckedChange: (next) => onChange?.(createEvent("change", { checked: next })),
56
58
  style: {
57
- ...rowStyle(colors, disabled),
59
+ ...rowStyle(theme, disabled),
58
60
  justifyContent: "space-between"
59
61
  },
60
62
  children: [label ? /* @__PURE__ */ jsx("span", { children: label }) : null, /* @__PURE__ */ jsx("span", {
@@ -81,13 +83,14 @@ const Switch$1 = ({ checked = false, label, disabled, onChange }) => {
81
83
  });
82
84
  };
83
85
  const Checkbox$1 = ({ checked = false, label, disabled, onChange }) => {
84
- const { colors } = useTheme();
86
+ const theme = useTheme();
87
+ const { colors } = theme;
85
88
  return /* @__PURE__ */ jsxs(CheckboxRoot, {
86
89
  className: "dot-checkbox",
87
90
  checked,
88
91
  disabled,
89
92
  onCheckedChange: (next) => onChange?.(createEvent("change", { checked: next })),
90
- style: rowStyle(colors, disabled),
93
+ style: rowStyle(theme, disabled),
91
94
  children: [/* @__PURE__ */ jsx(ChoiceMark, {
92
95
  round: false,
93
96
  checked,
@@ -122,13 +125,14 @@ const RadioGroup$1 = ({ value, label, disabled = false, onChange, children }) =>
122
125
  });
123
126
  };
124
127
  const Radio$1 = ({ value, label, disabled }) => {
125
- const { colors } = useTheme();
128
+ const theme = useTheme();
129
+ const { colors } = theme;
126
130
  if (value === void 0) return null;
127
131
  return /* @__PURE__ */ jsx(RadioRoot, {
128
132
  className: "dot-radio",
129
133
  value,
130
134
  disabled,
131
- style: (state) => rowStyle(colors, state.disabled),
135
+ style: (state) => rowStyle(theme, state.disabled),
132
136
  render: (props, state) => /* @__PURE__ */ jsxs("span", {
133
137
  ...props,
134
138
  children: [/* @__PURE__ */ jsx(ChoiceMark, {
@@ -0,0 +1,16 @@
1
+ //#region src/components/tokens.d.ts
2
+ export declare const SPACE: {
3
+ readonly none: 0;
4
+ readonly small: 4;
5
+ readonly medium: 8;
6
+ readonly large: 16;
7
+ };
8
+ export declare const FONT_SIZE: {
9
+ readonly caption: 13;
10
+ readonly body: 15;
11
+ readonly lead: 17;
12
+ readonly subtitle: 17;
13
+ readonly title: 20;
14
+ readonly display: 32;
15
+ };
16
+ //#endregion
@@ -20,6 +20,16 @@ const WEIGHTS = {
20
20
  };
21
21
  const CARD_RADIUS_SCALE = 1.5;
22
22
  const DISABLED_OPACITY = .6;
23
+ const SHADOWS = {
24
+ light: {
25
+ low: "0 1px 2px rgba(0, 0, 0, 0.06), 0 2px 8px rgba(0, 0, 0, 0.06)",
26
+ high: "0 4px 12px rgba(0, 0, 0, 0.08), 0 12px 32px rgba(0, 0, 0, 0.14)"
27
+ },
28
+ dark: {
29
+ low: "0 1px 2px rgba(0, 0, 0, 0.4), 0 2px 8px rgba(0, 0, 0, 0.3)",
30
+ high: "0 4px 12px rgba(0, 0, 0, 0.5), 0 12px 32px rgba(0, 0, 0, 0.5)"
31
+ }
32
+ };
23
33
  const CENTERED = {
24
34
  display: "flex",
25
35
  alignItems: "center",
@@ -46,4 +56,4 @@ const SELECTABLE = {
46
56
  WebkitUserSelect: "text"
47
57
  };
48
58
  //#endregion
49
- export { CARD_RADIUS_SCALE, CENTERED, DISABLED_OPACITY, FONT_SIZE, ICON_SIZE, PILL_STYLE, SELECTABLE, SPACE, WEIGHTS };
59
+ export { CARD_RADIUS_SCALE, CENTERED, DISABLED_OPACITY, FONT_SIZE, ICON_SIZE, PILL_STYLE, SELECTABLE, SHADOWS, SPACE, WEIGHTS };
@@ -1,10 +1,10 @@
1
+ import { SHADOWS } from "./tokens.js";
1
2
  import { useTheme } from "../theme.js";
2
- import { SPACE } from "./tokens.js";
3
3
  import { insets, paddingStyle } from "./padding.js";
4
+ import { boxStyle } from "./box.js";
4
5
  import { Footer as Footer$1 } from "./footer.js";
5
6
  import { pressable } from "./pressable.js";
6
- import { boxStyle } from "./box.js";
7
- import { createEvent } from "@monimesl/dot-core";
7
+ import { DEFAULT_VARIANTS, createEvent } from "@monimesl/dot-core";
8
8
  import { Children, isValidElement } from "react";
9
9
  import { jsx } from "react/jsx-runtime";
10
10
  //#region src/components/view.tsx
@@ -25,21 +25,30 @@ const CARD_LOOK = {
25
25
  border: "subtle",
26
26
  radius: "large"
27
27
  };
28
+ const RAISED_CARD_LOOK = {
29
+ ...CARD_LOOK,
30
+ border: "none"
31
+ };
28
32
  const View$1 = (props) => {
29
- const { direction = "column", gap = "medium", align = "stretch", justify = "start", wrap = false, grow = false, variant = "plain", onTap, children } = props;
33
+ const { direction = "column", gap = "medium", align = "stretch", justify = "start", wrap = false, grow = false, variant = DEFAULT_VARIANTS.View, onTap, children } = props;
30
34
  const theme = useTheme();
31
35
  const card = variant === "card";
36
+ const raisedCard = card && theme.elevation === "raised";
37
+ let cardLook;
38
+ if (card) cardLook = raisedCard ? RAISED_CARD_LOOK : CARD_LOOK;
39
+ const elevation = props.elevation ?? (raisedCard ? "low" : "none");
32
40
  const style = {
33
41
  display: "flex",
34
42
  flexDirection: direction,
35
43
  alignItems: ALIGN[align],
36
44
  justifyContent: JUSTIFY[justify],
37
45
  flexWrap: wrap ? "wrap" : "nowrap",
38
- gap: SPACE[gap],
39
- ...paddingStyle(props, card ? insets(SPACE.large) : void 0),
40
- ...boxStyle(props, theme, card ? CARD_LOOK : void 0),
46
+ gap: theme.space[gap],
47
+ ...paddingStyle(props, theme.space, card ? insets(theme.space.large) : void 0),
48
+ ...boxStyle(props, theme, cardLook),
41
49
  cursor: onTap ? "pointer" : void 0
42
50
  };
51
+ if (elevation !== "none") style.boxShadow = SHADOWS[theme.scheme][elevation];
43
52
  if (endsWithFooter(children)) style.paddingBottom = 0;
44
53
  if (grow) {
45
54
  style.flexGrow = 1;
package/dist/page-root.js CHANGED
@@ -1,18 +1,24 @@
1
- import { toList, toText } from "@monimesl/dot-core";
1
+ import { useTheme } from "./theme.js";
2
+ import { toList, toText, withComponentDefaults } from "@monimesl/dot-core";
2
3
  import { Fragment, createElement, useMemo, useSyncExternalStore } from "react";
3
4
  //#region src/page-root.tsx
4
5
  function PageRoot({ page, components }) {
5
6
  const state = useSyncExternalStore(page.subscribe, page.getState);
7
+ const themeComponents = useTheme().components;
6
8
  const context = useMemo(() => ({
7
9
  h(type, props, ...children) {
8
10
  const component = components[type];
9
11
  if (!component) throw new Error(`The renderer has no component for <${type}>. Check the tag's name, or pass a component for it to the renderer.`);
10
- return createElement(component, props, ...children);
12
+ return createElement(component, withComponentDefaults(type, props, themeComponents), ...children);
11
13
  },
12
14
  text: toText,
13
15
  on: (handler, data) => page.on(handler, data),
14
16
  each: (items, render, key) => createElement(Fragment, null, toList(items).map((item, index) => createElement(Fragment, { key: key ? String(key(item, index)) : index }, ...render(item, index))))
15
- }), [page, components]);
17
+ }), [
18
+ page,
19
+ components,
20
+ themeComponents
21
+ ]);
16
22
  if (!state) return null;
17
23
  return page.viewRenderer(state, context);
18
24
  }
@@ -1,5 +1,5 @@
1
- import { useTheme } from "./theme.js";
2
1
  import { CENTERED } from "./components/tokens.js";
2
+ import { useTheme } from "./theme.js";
3
3
  import { LoadingIcon } from "./components/spinner.js";
4
4
  import { useEffect, useRef, useState, useSyncExternalStore } from "react";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";