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

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 (55) 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 +65 -50
  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 +6 -11
  15. package/dist/components/grid.js +20 -13
  16. package/dist/components/icon-button.js +1 -1
  17. package/dist/components/icon.js +32 -5
  18. package/dist/components/index.d.ts +2 -1
  19. package/dist/components/index.js +3 -1
  20. package/dist/components/input.js +1 -1
  21. package/dist/components/link.js +1 -1
  22. package/dist/components/list.js +11 -9
  23. package/dist/components/option.js +3 -3
  24. package/dist/components/padding.js +9 -10
  25. package/dist/components/pinned-bar.js +29 -0
  26. package/dist/components/pinned.d.ts +6 -0
  27. package/dist/components/pinned.js +26 -0
  28. package/dist/components/prose.js +23 -20
  29. package/dist/components/rich-text.js +30 -18
  30. package/dist/components/scroll.js +25 -8
  31. package/dist/components/select.js +1 -1
  32. package/dist/components/sheet.js +51 -45
  33. package/dist/components/side-room.js +5 -0
  34. package/dist/components/skeleton.js +1 -1
  35. package/dist/components/slider.js +3 -3
  36. package/dist/components/spinner.js +1 -1
  37. package/dist/components/stack.js +12 -8
  38. package/dist/components/stepper.js +3 -3
  39. package/dist/components/steps.js +17 -14
  40. package/dist/components/tabs.js +72 -26
  41. package/dist/components/text.js +12 -14
  42. package/dist/components/toast.js +3 -3
  43. package/dist/components/toggles.js +13 -9
  44. package/dist/components/tokens.d.ts +16 -0
  45. package/dist/components/tokens.js +20 -1
  46. package/dist/components/view.js +29 -15
  47. package/dist/index.d.ts +2 -1
  48. package/dist/index.js +2 -1
  49. package/dist/page-root.js +9 -3
  50. package/dist/pull-to-refresh.js +1 -1
  51. package/dist/root.js +4 -3
  52. package/dist/styles.css +1 -1
  53. package/dist/theme.d.ts +12 -1
  54. package/dist/theme.js +85 -15
  55. package/package.json +4 -4
@@ -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, 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,69 +1,93 @@
1
+ import { CENTERED, ICON_SIZE, 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
+ 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 }) => {
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,
@@ -71,24 +95,46 @@ const Tab$1 = ({ value, label, badge }) => {
71
95
  ...CENTERED,
72
96
  gap: 6,
73
97
  flex: "1 0 auto",
74
- minHeight: segmented ? 36 : 44,
75
98
  padding: "0 12px",
76
99
  border: "none",
77
- fontSize: FONT_SIZE.body,
100
+ fontSize: fontSize.body,
78
101
  fontWeight: selected ? WEIGHTS.bold : WEIGHTS.medium,
79
102
  whiteSpace: "nowrap",
80
103
  color,
81
104
  cursor: "pointer",
82
105
  ...variantStyle
83
106
  },
84
- children: [label, badge ? /* @__PURE__ */ jsx("span", {
107
+ children: [icon ? /* @__PURE__ */ jsxs("span", {
85
108
  style: {
86
- ...PILL_STYLE,
87
- background: colors.primary,
88
- color: colors.onPrimary
109
+ position: "relative",
110
+ display: "inline-flex"
89
111
  },
90
- children: badge
91
- }) : null]
112
+ children: [/* @__PURE__ */ jsx(IconGraphic, {
113
+ name: icon,
114
+ size: bar ? BAR_ICON_SIZE : ICON_SIZE.medium,
115
+ color: "currentColor"
116
+ }), countOnIcon && count ? /* @__PURE__ */ jsx("span", {
117
+ style: {
118
+ position: "absolute",
119
+ top: -6,
120
+ insetInlineStart: 16
121
+ },
122
+ children: count
123
+ }) : null]
124
+ }) : null, /* @__PURE__ */ jsxs("span", {
125
+ style: {
126
+ ...CENTERED,
127
+ gap: 6,
128
+ maxWidth: "100%"
129
+ },
130
+ children: [/* @__PURE__ */ jsx("span", {
131
+ style: {
132
+ overflow: "hidden",
133
+ textOverflow: "ellipsis"
134
+ },
135
+ children: label
136
+ }), countOnIcon ? null : count]
137
+ })]
92
138
  });
93
139
  };
94
140
  //#endregion
@@ -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,10 +50,12 @@ 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: namedVariant, 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);
57
+ let variant = namedVariant ?? DEFAULT_VARIANTS.Text;
58
+ if (!Object.hasOwn(VARIANTS, variant)) variant = DEFAULT_VARIANTS.Text;
57
59
  const { heading, lineHeight, weight: defaultWeight } = VARIANTS[variant];
58
60
  const defaultLeading = inProse && !heading ? "relaxed" : "normal";
59
61
  const style = {
@@ -61,16 +63,17 @@ const Text = ({ variant = "body", tone, weight, align, maxLines, decoration, num
61
63
  marginInline: 0,
62
64
  marginBlockEnd: 0,
63
65
  marginBlockStart: inProse && heading ? void 0 : 0,
64
- fontSize: FONT_SIZE[variant],
65
- fontWeight: WEIGHTS[weight ?? defaultWeight],
66
+ fontSize: theme.fontSize[variant],
67
+ fontFamily: heading ? theme.headingFontFamily : void 0,
68
+ fontWeight: WEIGHTS[weight ?? (heading ? theme.headingWeight : void 0) ?? defaultWeight],
66
69
  fontStyle: italic ? "italic" : void 0,
67
70
  letterSpacing: variant === "display" ? "-0.02em" : "normal",
68
- color: tone ? textColor(tone, theme) : "inherit",
71
+ color: tone ? textToneColor(tone, theme) : "inherit",
69
72
  textAlign: align,
70
73
  textDecorationLine: decoration ? DECORATION[decoration] : void 0,
71
74
  fontVariantNumeric: numeric ? "tabular-nums" : void 0,
72
75
  ...selectable ? SELECTABLE : void 0,
73
- ...paddingStyle(padding)
76
+ ...paddingStyle(padding, theme.space)
74
77
  };
75
78
  if (!insideText) {
76
79
  style.lineHeight = lineHeight + LEADING_CHANGE[leading ?? defaultLeading];
@@ -98,10 +101,5 @@ const Text = ({ variant = "body", tone, weight, align, maxLines, decoration, num
98
101
  children: content
99
102
  });
100
103
  };
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
104
  //#endregion
107
- export { Text };
105
+ 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,25 @@ 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
+ };
33
+ const SHADOW_REACH = {
34
+ top: 20,
35
+ sides: 32,
36
+ bottom: 44
37
+ };
38
+ const SCROLL_SHADOW_ROOM = {
39
+ top: 6,
40
+ bottom: 10
41
+ };
23
42
  const CENTERED = {
24
43
  display: "flex",
25
44
  alignItems: "center",
@@ -46,4 +65,4 @@ const SELECTABLE = {
46
65
  WebkitUserSelect: "text"
47
66
  };
48
67
  //#endregion
49
- export { CARD_RADIUS_SCALE, CENTERED, DISABLED_OPACITY, FONT_SIZE, ICON_SIZE, PILL_STYLE, SELECTABLE, SPACE, WEIGHTS };
68
+ export { CARD_RADIUS_SCALE, CENTERED, DISABLED_OPACITY, FONT_SIZE, ICON_SIZE, PILL_STYLE, SCROLL_SHADOW_ROOM, SELECTABLE, SHADOWS, SHADOW_REACH, SPACE, WEIGHTS };
@@ -1,11 +1,11 @@
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 { Footer as Footer$1 } from "./footer.js";
5
- import { pressable } from "./pressable.js";
4
+ import { SideRoomContext } from "./side-room.js";
6
5
  import { boxStyle } from "./box.js";
7
- import { createEvent } from "@monimesl/dot-core";
8
- import { Children, isValidElement } from "react";
6
+ import { pressable } from "./pressable.js";
7
+ import { DEFAULT_VARIANTS, createEvent } from "@monimesl/dot-core";
8
+ import { useContext } from "react";
9
9
  import { jsx } from "react/jsx-runtime";
10
10
  //#region src/components/view.tsx
11
11
  const ALIGN = {
@@ -25,22 +25,36 @@ 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 { id, direction = "column", gap = "medium", align = "stretch", justify = "start", wrap = false, grow = false, variant = DEFAULT_VARIANTS.View, onTap, children } = props;
30
34
  const theme = useTheme();
35
+ const sideRoomAround = useContext(SideRoomContext);
31
36
  const card = variant === "card";
37
+ const raisedCard = card && theme.elevation === "raised" && props.elevation !== "none";
38
+ let cardLook;
39
+ if (card) cardLook = raisedCard ? RAISED_CARD_LOOK : CARD_LOOK;
40
+ const elevation = props.elevation ?? (raisedCard ? "low" : "none");
41
+ const padding = paddingStyle(props, theme.space, card ? insets(theme.space.large) : void 0);
32
42
  const style = {
33
43
  display: "flex",
34
44
  flexDirection: direction,
35
45
  alignItems: ALIGN[align],
36
46
  justifyContent: JUSTIFY[justify],
37
47
  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),
48
+ gap: theme.space[gap],
49
+ ...padding,
50
+ "--dot-view-top": `${padding.paddingTop}px`,
51
+ "--dot-view-bottom": `${padding.paddingBottom}px`,
52
+ "--dot-view-start": `${padding.paddingInlineStart}px`,
53
+ "--dot-view-end": `${padding.paddingInlineEnd}px`,
54
+ ...boxStyle(props, theme, cardLook),
41
55
  cursor: onTap ? "pointer" : void 0
42
56
  };
43
- if (endsWithFooter(children)) style.paddingBottom = 0;
57
+ if (elevation !== "none") style.boxShadow = SHADOWS[theme.scheme][elevation];
44
58
  if (grow) {
45
59
  style.flexGrow = 1;
46
60
  style.minWidth = 0;
@@ -48,14 +62,14 @@ const View$1 = (props) => {
48
62
  const press = onTap ? pressable(() => onTap(createEvent("tap"))) : void 0;
49
63
  return /* @__PURE__ */ jsx("div", {
50
64
  className: "dot-view",
65
+ "data-dot-view": id,
51
66
  style,
52
67
  ...press,
53
- children
68
+ children: /* @__PURE__ */ jsx(SideRoomContext.Provider, {
69
+ value: sideRoomAround && direction !== "row",
70
+ children
71
+ })
54
72
  });
55
73
  };
56
- function endsWithFooter(children) {
57
- const last = Children.toArray(children).at(-1);
58
- return isValidElement(last) && last.type === Footer$1;
59
- }
60
74
  //#endregion
61
75
  export { View$1 as View };
package/dist/index.d.ts CHANGED
@@ -20,6 +20,7 @@ import { Input } from "./components/input.js";
20
20
  import { Link } from "./components/link.js";
21
21
  import { List, ListItem } from "./components/list.js";
22
22
  import { Option } from "./components/option.js";
23
+ import { Pinned } from "./components/pinned.js";
23
24
  import { Bullet, BulletList, Prose, Quote } from "./components/prose.js";
24
25
  import { QRCode } from "./components/qr-code.js";
25
26
  import { RichText } from "./components/rich-text.js";
@@ -40,4 +41,4 @@ import { Checkbox, Radio, RadioGroup, Switch } from "./components/toggles.js";
40
41
  import { View } from "./components/view.js";
41
42
  import "./components/index.js";
42
43
  import { ResolvedColors, ResolvedTheme, resolveTheme, useTheme } from "./theme.js";
43
- export { AmountInput, Avatar, Badge, type BuiltinReactComponents, Bullet, BulletList, Button, Carousel, Checkbox, Chip, CodeInput, type CreateReactRendererOptions, DetailRow, Disclosure, Divider, EmptyState, Footer, Grid, GridItem, Icon, Image, Input, Link, List, ListItem, Notice, Option, ProgressBar, Prose, QRCode, Quote, Radio, RadioGroup, type ReactComponent, type ReactComponents, type ReactRendererOptions, type ResolvedColors, type ResolvedTheme, RichText, Scroll, Select, Sheet, Skeleton, Slider, Spinner, Stack, Step, Stepper, Steps, Switch, Tab, Tabs, Text, TextArea, Toast, View, type Wrapper, createReactRenderer, reactRenderer as default, resolveTheme, useTheme };
44
+ export { AmountInput, Avatar, Badge, type BuiltinReactComponents, Bullet, BulletList, Button, Carousel, Checkbox, Chip, CodeInput, type CreateReactRendererOptions, DetailRow, Disclosure, Divider, EmptyState, Footer, Grid, GridItem, Icon, Image, Input, Link, List, ListItem, Notice, Option, Pinned, ProgressBar, Prose, QRCode, Quote, Radio, RadioGroup, type ReactComponent, type ReactComponents, type ReactRendererOptions, type ResolvedColors, type ResolvedTheme, RichText, Scroll, Select, Sheet, Skeleton, Slider, Spinner, Stack, Step, Stepper, Steps, Switch, Tab, Tabs, Text, TextArea, Toast, View, type Wrapper, createReactRenderer, reactRenderer as default, resolveTheme, useTheme };
package/dist/index.js CHANGED
@@ -19,6 +19,7 @@ import { Input } from "./components/input.js";
19
19
  import { Link } from "./components/link.js";
20
20
  import { List, ListItem } from "./components/list.js";
21
21
  import { Option } from "./components/option.js";
22
+ import { Pinned } from "./components/pinned.js";
22
23
  import { Bullet, BulletList, Prose, Quote } from "./components/prose.js";
23
24
  import { QRCode } from "./components/qr-code.js";
24
25
  import { Text } from "./components/text.js";
@@ -40,4 +41,4 @@ import { createReactRenderer, reactRenderer } from "./renderer.js";
40
41
  //#region src/index.ts
41
42
  var src_default = reactRenderer;
42
43
  //#endregion
43
- export { AmountInput, Avatar, Badge, Bullet, BulletList, Button, Carousel, Checkbox, Chip, CodeInput, DetailRow, Disclosure, Divider, EmptyState, Footer, Grid, GridItem, Icon, Image, Input, Link, List, ListItem, Notice, Option, ProgressBar, Prose, QRCode, Quote, Radio, RadioGroup, RichText, Scroll, Select, Sheet, Skeleton, Slider, Spinner, Stack, Step, Stepper, Steps, Switch, Tab, Tabs, Text, TextArea, Toast, View, createReactRenderer, src_default as default, resolveTheme, useTheme };
44
+ export { AmountInput, Avatar, Badge, Bullet, BulletList, Button, Carousel, Checkbox, Chip, CodeInput, DetailRow, Disclosure, Divider, EmptyState, Footer, Grid, GridItem, Icon, Image, Input, Link, List, ListItem, Notice, Option, Pinned, ProgressBar, Prose, QRCode, Quote, Radio, RadioGroup, RichText, Scroll, Select, Sheet, Skeleton, Slider, Spinner, Stack, Step, Stepper, Steps, Switch, Tab, Tabs, Text, TextArea, Toast, View, createReactRenderer, src_default as default, resolveTheme, useTheme };