@monimesl/dot-renderer-react 0.1.0-alpha.21 → 0.1.0-alpha.24
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/README.md +5 -3
- package/dist/color.js +5 -18
- package/dist/components/amount-input.js +9 -7
- package/dist/components/avatar.js +9 -4
- package/dist/components/box.js +3 -5
- package/dist/components/carousel.js +56 -52
- package/dist/components/code-input.js +6 -7
- package/dist/components/empty-state.js +2 -4
- package/dist/components/feedback.js +1 -1
- package/dist/components/grid.js +4 -5
- package/dist/components/list.js +10 -12
- package/dist/components/numbers.js +9 -0
- package/dist/components/padding.js +9 -6
- package/dist/components/scroll.js +11 -9
- package/dist/components/sheet.js +3 -3
- package/dist/components/slider.js +5 -5
- package/dist/components/stepper.js +5 -7
- package/dist/components/steps.js +4 -6
- package/dist/components/tabs.js +23 -19
- package/dist/components/text.js +6 -5
- package/dist/components/toggles.js +2 -4
- package/dist/components/tokens.js +6 -1
- package/dist/markdown.js +26 -22
- package/dist/pull-to-refresh.js +28 -26
- package/dist/root.js +23 -10
- package/dist/theme.d.ts +2 -2
- package/dist/theme.js +52 -16
- package/package.json +4 -4
- package/dist/components/utils.js +0 -6
|
@@ -8,9 +8,9 @@ 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
10
|
const { colors } = useTheme();
|
|
11
|
-
const [
|
|
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
|
-
const
|
|
13
|
+
const shownValue = positionText === "" ? String(min) : positionText;
|
|
14
14
|
return /* @__PURE__ */ jsxs(Field, {
|
|
15
15
|
label: void 0,
|
|
16
16
|
hint,
|
|
@@ -27,7 +27,7 @@ const Slider$1 = ({ value, min = 0, max = 100, step = 1, showValue, label, hint,
|
|
|
27
27
|
color: colors.subtle,
|
|
28
28
|
fontVariantNumeric: "tabular-nums"
|
|
29
29
|
},
|
|
30
|
-
children:
|
|
30
|
+
children: shownValue
|
|
31
31
|
}) : null]
|
|
32
32
|
}) : null, /* @__PURE__ */ jsx("input", {
|
|
33
33
|
className: "dot-slider",
|
|
@@ -35,13 +35,13 @@ const Slider$1 = ({ value, min = 0, max = 100, step = 1, showValue, label, hint,
|
|
|
35
35
|
min,
|
|
36
36
|
max,
|
|
37
37
|
step,
|
|
38
|
-
value:
|
|
38
|
+
value: shownValue,
|
|
39
39
|
disabled,
|
|
40
40
|
"aria-label": label,
|
|
41
41
|
...controlAttributes,
|
|
42
42
|
onChange: (event) => {
|
|
43
43
|
const next = event.currentTarget.value;
|
|
44
|
-
|
|
44
|
+
showPosition(next);
|
|
45
45
|
onChange?.(createEvent("change", { value: Number(next) }));
|
|
46
46
|
},
|
|
47
47
|
style: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useTheme } from "../theme.js";
|
|
2
|
-
import { DISABLED_OPACITY, FONT_SIZE, ICON_SIZE, WEIGHTS } from "./tokens.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";
|
|
@@ -9,11 +9,11 @@ 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
11
|
const { colors } = useTheme();
|
|
12
|
-
const [
|
|
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
|
-
const current =
|
|
14
|
+
const current = shownText === "" ? min ?? 0 : Number(shownText);
|
|
15
15
|
const moveTo = (next) => {
|
|
16
|
-
|
|
16
|
+
showText(String(next));
|
|
17
17
|
onChange?.(createEvent("change", { value: next }));
|
|
18
18
|
};
|
|
19
19
|
const atMin = min !== void 0 && current - step < min;
|
|
@@ -71,9 +71,7 @@ function StepButton({ icon, label, disabled, onPress }) {
|
|
|
71
71
|
disabled,
|
|
72
72
|
onClick: onPress,
|
|
73
73
|
style: {
|
|
74
|
-
|
|
75
|
-
alignItems: "center",
|
|
76
|
-
justifyContent: "center",
|
|
74
|
+
...CENTERED,
|
|
77
75
|
width: 40,
|
|
78
76
|
height: 40,
|
|
79
77
|
border: "none",
|
package/dist/components/steps.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useTheme } from "../theme.js";
|
|
2
|
-
import { FONT_SIZE, WEIGHTS } from "./tokens.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";
|
|
@@ -15,7 +15,7 @@ const Steps = ({ children, ...padding }) => /* @__PURE__ */ jsx("ol", {
|
|
|
15
15
|
},
|
|
16
16
|
children
|
|
17
17
|
});
|
|
18
|
-
function
|
|
18
|
+
function stepMark(colors, status) {
|
|
19
19
|
switch (status) {
|
|
20
20
|
case "done": return {
|
|
21
21
|
background: colors.success,
|
|
@@ -41,7 +41,7 @@ function mark(colors, status) {
|
|
|
41
41
|
}
|
|
42
42
|
const Step = ({ title, text, status = "upcoming" }) => {
|
|
43
43
|
const { colors } = useTheme();
|
|
44
|
-
const { background, border, icon } =
|
|
44
|
+
const { background, border, icon } = stepMark(colors, status);
|
|
45
45
|
return /* @__PURE__ */ jsxs("li", {
|
|
46
46
|
className: "dot-step",
|
|
47
47
|
"aria-current": status === "current" ? "step" : void 0,
|
|
@@ -58,9 +58,7 @@ const Step = ({ title, text, status = "upcoming" }) => {
|
|
|
58
58
|
},
|
|
59
59
|
children: [/* @__PURE__ */ jsx("span", {
|
|
60
60
|
style: {
|
|
61
|
-
|
|
62
|
-
alignItems: "center",
|
|
63
|
-
justifyContent: "center",
|
|
61
|
+
...CENTERED,
|
|
64
62
|
flexShrink: 0,
|
|
65
63
|
width: MARK_SIZE,
|
|
66
64
|
height: MARK_SIZE,
|
package/dist/components/tabs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useTheme } from "../theme.js";
|
|
2
|
-
import { FONT_SIZE, PILL_STYLE, WEIGHTS } from "./tokens.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";
|
|
@@ -15,6 +15,14 @@ const TabsContext = createContext({
|
|
|
15
15
|
const Tabs$1 = ({ value, variant = "underline", onChange, children, ...padding }) => {
|
|
16
16
|
const { colors, radius } = useTheme();
|
|
17
17
|
const segmented = variant === "segmented";
|
|
18
|
+
let variantStyle;
|
|
19
|
+
if (segmented) variantStyle = {
|
|
20
|
+
gap: 2,
|
|
21
|
+
padding: 3,
|
|
22
|
+
borderRadius: radius,
|
|
23
|
+
background: colors.muted
|
|
24
|
+
};
|
|
25
|
+
else variantStyle = { borderBottom: `1px solid ${colors.border}` };
|
|
18
26
|
return /* @__PURE__ */ jsx(TabsRoot, {
|
|
19
27
|
value: value ?? null,
|
|
20
28
|
onValueChange: (next) => {
|
|
@@ -26,12 +34,7 @@ const Tabs$1 = ({ value, variant = "underline", onChange, children, ...padding }
|
|
|
26
34
|
style: {
|
|
27
35
|
display: "flex",
|
|
28
36
|
overflowX: "auto",
|
|
29
|
-
...
|
|
30
|
-
gap: 2,
|
|
31
|
-
padding: 3,
|
|
32
|
-
borderRadius: radius,
|
|
33
|
-
background: colors.muted
|
|
34
|
-
} : { borderBottom: `1px solid ${colors.border}` }
|
|
37
|
+
...variantStyle
|
|
35
38
|
},
|
|
36
39
|
children: /* @__PURE__ */ jsx(TabsContext.Provider, {
|
|
37
40
|
value: {
|
|
@@ -50,13 +53,22 @@ const Tab$1 = ({ value, label, badge }) => {
|
|
|
50
53
|
const selected = value === chosen;
|
|
51
54
|
let color = colors.subtle;
|
|
52
55
|
if (selected) color = segmented ? colors.text : colors.primary;
|
|
56
|
+
let variantStyle;
|
|
57
|
+
if (segmented) variantStyle = {
|
|
58
|
+
borderRadius: Math.max(radius - 2, 0),
|
|
59
|
+
background: selected ? colors.surface : "transparent",
|
|
60
|
+
boxShadow: selected ? "0 1px 3px rgba(0, 0, 0, 0.15)" : "none"
|
|
61
|
+
};
|
|
62
|
+
else variantStyle = {
|
|
63
|
+
marginBottom: -1,
|
|
64
|
+
background: "transparent",
|
|
65
|
+
borderBottom: `2px solid ${selected ? colors.primary : "transparent"}`
|
|
66
|
+
};
|
|
53
67
|
return /* @__PURE__ */ jsxs(TabsTab, {
|
|
54
68
|
className: "dot-tab",
|
|
55
69
|
value,
|
|
56
70
|
style: {
|
|
57
|
-
|
|
58
|
-
alignItems: "center",
|
|
59
|
-
justifyContent: "center",
|
|
71
|
+
...CENTERED,
|
|
60
72
|
gap: 6,
|
|
61
73
|
flex: "1 0 auto",
|
|
62
74
|
minHeight: segmented ? 36 : 44,
|
|
@@ -67,15 +79,7 @@ const Tab$1 = ({ value, label, badge }) => {
|
|
|
67
79
|
whiteSpace: "nowrap",
|
|
68
80
|
color,
|
|
69
81
|
cursor: "pointer",
|
|
70
|
-
...
|
|
71
|
-
borderRadius: Math.max(radius - 2, 0),
|
|
72
|
-
background: selected ? colors.surface : "transparent",
|
|
73
|
-
boxShadow: selected ? "0 1px 3px rgba(0, 0, 0, 0.15)" : "none"
|
|
74
|
-
} : {
|
|
75
|
-
marginBottom: -1,
|
|
76
|
-
background: "transparent",
|
|
77
|
-
borderBottom: `2px solid ${selected ? colors.primary : "transparent"}`
|
|
78
|
-
}
|
|
82
|
+
...variantStyle
|
|
79
83
|
},
|
|
80
84
|
children: [label, badge ? /* @__PURE__ */ jsx("span", {
|
|
81
85
|
style: {
|
package/dist/components/text.js
CHANGED
|
@@ -52,12 +52,12 @@ const DECORATION = {
|
|
|
52
52
|
};
|
|
53
53
|
const Text = ({ variant = "body", tone, weight, align, maxLines, decoration, numeric, leading, italic, selectable, children, ...padding }) => {
|
|
54
54
|
const theme = useTheme();
|
|
55
|
-
const
|
|
55
|
+
const insideText = useContext(InsideText);
|
|
56
56
|
const inProse = useContext(InsideProse);
|
|
57
57
|
const { heading, lineHeight, weight: defaultWeight } = VARIANTS[variant];
|
|
58
58
|
const defaultLeading = inProse && !heading ? "relaxed" : "normal";
|
|
59
59
|
const style = {
|
|
60
|
-
display:
|
|
60
|
+
display: insideText ? "inline" : "block",
|
|
61
61
|
marginInline: 0,
|
|
62
62
|
marginBlockEnd: 0,
|
|
63
63
|
marginBlockStart: inProse && heading ? void 0 : 0,
|
|
@@ -72,7 +72,7 @@ const Text = ({ variant = "body", tone, weight, align, maxLines, decoration, num
|
|
|
72
72
|
...selectable ? SELECTABLE : void 0,
|
|
73
73
|
...paddingStyle(padding)
|
|
74
74
|
};
|
|
75
|
-
if (!
|
|
75
|
+
if (!insideText) {
|
|
76
76
|
style.lineHeight = lineHeight + LEADING_CHANGE[leading ?? defaultLeading];
|
|
77
77
|
style.textWrap = heading ? "balance" : "pretty";
|
|
78
78
|
style.overflowWrap = "anywhere";
|
|
@@ -87,7 +87,7 @@ const Text = ({ variant = "body", tone, weight, align, maxLines, decoration, num
|
|
|
87
87
|
value: true,
|
|
88
88
|
children
|
|
89
89
|
});
|
|
90
|
-
if ((variant === "title" || variant === "subtitle") && !
|
|
90
|
+
if ((variant === "title" || variant === "subtitle") && !insideText) return /* @__PURE__ */ jsx(variant === "title" ? "h2" : "h3", {
|
|
91
91
|
className: "dot-text dot-heading",
|
|
92
92
|
style,
|
|
93
93
|
children: content
|
|
@@ -100,7 +100,8 @@ const Text = ({ variant = "body", tone, weight, align, maxLines, decoration, num
|
|
|
100
100
|
};
|
|
101
101
|
function textColor(tone, theme) {
|
|
102
102
|
if (isTone(tone)) return toneColor(theme.colors, tone);
|
|
103
|
-
|
|
103
|
+
if (tone === "onPrimary") return theme.colors.onPrimary;
|
|
104
|
+
return customColor(tone, theme);
|
|
104
105
|
}
|
|
105
106
|
//#endregion
|
|
106
107
|
export { Text };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useTheme } from "../theme.js";
|
|
2
|
-
import { DISABLED_OPACITY, FONT_SIZE, ICON_SIZE, SPACE } from "./tokens.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";
|
|
@@ -35,9 +35,7 @@ function ChoiceMark({ round, checked, children }) {
|
|
|
35
35
|
const filled = checked && !round;
|
|
36
36
|
return /* @__PURE__ */ jsx("span", {
|
|
37
37
|
style: {
|
|
38
|
-
|
|
39
|
-
alignItems: "center",
|
|
40
|
-
justifyContent: "center",
|
|
38
|
+
...CENTERED,
|
|
41
39
|
flexShrink: 0,
|
|
42
40
|
width: 22,
|
|
43
41
|
height: 22,
|
|
@@ -20,6 +20,11 @@ const WEIGHTS = {
|
|
|
20
20
|
};
|
|
21
21
|
const CARD_RADIUS_SCALE = 1.5;
|
|
22
22
|
const DISABLED_OPACITY = .6;
|
|
23
|
+
const CENTERED = {
|
|
24
|
+
display: "flex",
|
|
25
|
+
alignItems: "center",
|
|
26
|
+
justifyContent: "center"
|
|
27
|
+
};
|
|
23
28
|
const ICON_SIZE = {
|
|
24
29
|
small: 16,
|
|
25
30
|
medium: 20,
|
|
@@ -41,4 +46,4 @@ const SELECTABLE = {
|
|
|
41
46
|
WebkitUserSelect: "text"
|
|
42
47
|
};
|
|
43
48
|
//#endregion
|
|
44
|
-
export { CARD_RADIUS_SCALE, DISABLED_OPACITY, FONT_SIZE, ICON_SIZE, PILL_STYLE, SELECTABLE, SPACE, WEIGHTS };
|
|
49
|
+
export { CARD_RADIUS_SCALE, CENTERED, DISABLED_OPACITY, FONT_SIZE, ICON_SIZE, PILL_STYLE, SELECTABLE, SPACE, WEIGHTS };
|
package/dist/markdown.js
CHANGED
|
@@ -148,13 +148,15 @@ function parseInline(text) {
|
|
|
148
148
|
take({ kind: "break" }, 1);
|
|
149
149
|
continue;
|
|
150
150
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
151
|
+
if (char === "`") {
|
|
152
|
+
const codeEnd = text.indexOf("`", index + 1);
|
|
153
|
+
if (codeEnd > index + 1) {
|
|
154
|
+
take({
|
|
155
|
+
kind: "code",
|
|
156
|
+
text: text.slice(index + 1, codeEnd)
|
|
157
|
+
}, codeEnd + 1 - index);
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
158
160
|
}
|
|
159
161
|
const link = LINK.exec(rest);
|
|
160
162
|
if (link) {
|
|
@@ -182,21 +184,23 @@ function parseInline(text) {
|
|
|
182
184
|
}, whole.length);
|
|
183
185
|
continue;
|
|
184
186
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
187
|
+
if (char === "*" || char === "_") {
|
|
188
|
+
const strong = between(text, index, char + char);
|
|
189
|
+
if (strong) {
|
|
190
|
+
take({
|
|
191
|
+
kind: "strong",
|
|
192
|
+
children: parseInline(strong.inner)
|
|
193
|
+
}, strong.length);
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
const emphasis = between(text, index, char);
|
|
197
|
+
if (emphasis) {
|
|
198
|
+
take({
|
|
199
|
+
kind: "emphasis",
|
|
200
|
+
children: parseInline(emphasis.inner)
|
|
201
|
+
}, emphasis.length);
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
200
204
|
}
|
|
201
205
|
plain += char;
|
|
202
206
|
index += 1;
|
package/dist/pull-to-refresh.js
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import { useTheme } from "./theme.js";
|
|
2
|
+
import { CENTERED } from "./components/tokens.js";
|
|
2
3
|
import { LoadingIcon } from "./components/spinner.js";
|
|
3
4
|
import { useEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
4
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
6
|
//#region src/pull-to-refresh.tsx
|
|
6
7
|
const PULL_DISTANCE = 64;
|
|
8
|
+
const LONGEST_PULL = PULL_DISTANCE * 1.5;
|
|
7
9
|
const RESISTANCE = .5;
|
|
8
10
|
const INDICATOR_SIZE = 36;
|
|
9
11
|
const DRAG_DISTANCE = 6;
|
|
10
12
|
function PullToRefresh({ page, children }) {
|
|
11
13
|
const { colors } = useTheme();
|
|
12
14
|
const refreshing = useSyncExternalStore(page.subscribeToRefreshing, page.isRefreshing);
|
|
13
|
-
const [
|
|
14
|
-
const
|
|
15
|
+
const [pullDistance, setPullDistance] = useState(0);
|
|
16
|
+
const areaRef = useRef(null);
|
|
15
17
|
useEffect(() => {
|
|
16
|
-
const
|
|
17
|
-
const view =
|
|
18
|
+
const area = areaRef.current;
|
|
19
|
+
const view = area.ownerDocument.defaultView;
|
|
18
20
|
let startY;
|
|
19
21
|
let pulled = 0;
|
|
20
22
|
let dragged = false;
|
|
@@ -28,19 +30,19 @@ function PullToRefresh({ page, children }) {
|
|
|
28
30
|
const distance = (y - startY) * RESISTANCE;
|
|
29
31
|
if (distance <= 0) {
|
|
30
32
|
pulled = 0;
|
|
31
|
-
|
|
33
|
+
setPullDistance(0);
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
34
36
|
if (event.cancelable) event.preventDefault();
|
|
35
37
|
if (distance > DRAG_DISTANCE) dragged = true;
|
|
36
|
-
pulled = Math.min(distance,
|
|
37
|
-
|
|
38
|
+
pulled = Math.min(distance, LONGEST_PULL);
|
|
39
|
+
setPullDistance(pulled);
|
|
38
40
|
};
|
|
39
41
|
const end = () => {
|
|
40
42
|
if (startY !== void 0 && pulled >= PULL_DISTANCE) page.refresh();
|
|
41
43
|
startY = void 0;
|
|
42
44
|
pulled = 0;
|
|
43
|
-
|
|
45
|
+
setPullDistance(0);
|
|
44
46
|
};
|
|
45
47
|
const ignoreDragClick = (event) => {
|
|
46
48
|
if (dragged) {
|
|
@@ -55,25 +57,27 @@ function PullToRefresh({ page, children }) {
|
|
|
55
57
|
if (event.button === 0) begin(event.clientY);
|
|
56
58
|
};
|
|
57
59
|
const mouseMove = (event) => move(event.clientY, event);
|
|
58
|
-
const
|
|
59
|
-
listen(
|
|
60
|
-
listen(
|
|
61
|
-
listen(
|
|
62
|
-
listen(
|
|
63
|
-
listen(
|
|
64
|
-
listen(
|
|
60
|
+
const removeListeners = [
|
|
61
|
+
listen(area, "touchstart", touchStart, { passive: true }),
|
|
62
|
+
listen(area, "touchmove", touchMove, { passive: false }),
|
|
63
|
+
listen(area, "touchend", end),
|
|
64
|
+
listen(area, "touchcancel", end),
|
|
65
|
+
listen(area, "mousedown", mouseDown),
|
|
66
|
+
listen(area, "click", ignoreDragClick, { capture: true }),
|
|
65
67
|
listen(view, "mousemove", mouseMove),
|
|
66
68
|
listen(view, "mouseup", end)
|
|
67
69
|
];
|
|
68
|
-
return () =>
|
|
70
|
+
return () => {
|
|
71
|
+
for (const removeListener of removeListeners) removeListener();
|
|
72
|
+
};
|
|
69
73
|
}, [page]);
|
|
70
|
-
const
|
|
71
|
-
const
|
|
74
|
+
const indicatorDistance = refreshing ? PULL_DISTANCE : pullDistance;
|
|
75
|
+
const arrowTurn = Math.min(pullDistance, PULL_DISTANCE) / PULL_DISTANCE * 180;
|
|
72
76
|
return /* @__PURE__ */ jsxs("div", {
|
|
73
|
-
ref:
|
|
77
|
+
ref: areaRef,
|
|
74
78
|
className: "dot-pull-to-refresh",
|
|
75
79
|
style: { display: "contents" },
|
|
76
|
-
children: [children,
|
|
80
|
+
children: [children, indicatorDistance > 0 ? /* @__PURE__ */ jsx("span", {
|
|
77
81
|
role: refreshing ? "status" : void 0,
|
|
78
82
|
"aria-label": refreshing ? "Refreshing" : void 0,
|
|
79
83
|
style: {
|
|
@@ -81,9 +85,7 @@ function PullToRefresh({ page, children }) {
|
|
|
81
85
|
top: 0,
|
|
82
86
|
left: "50%",
|
|
83
87
|
zIndex: 2,
|
|
84
|
-
|
|
85
|
-
alignItems: "center",
|
|
86
|
-
justifyContent: "center",
|
|
88
|
+
...CENTERED,
|
|
87
89
|
width: INDICATOR_SIZE,
|
|
88
90
|
height: INDICATOR_SIZE,
|
|
89
91
|
marginLeft: -18,
|
|
@@ -91,8 +93,8 @@ function PullToRefresh({ page, children }) {
|
|
|
91
93
|
background: colors.surface,
|
|
92
94
|
color: colors.primary,
|
|
93
95
|
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.2)",
|
|
94
|
-
transform: `translateY(${
|
|
95
|
-
transition:
|
|
96
|
+
transform: `translateY(${indicatorDistance - INDICATOR_SIZE / 2}px)`,
|
|
97
|
+
transition: pullDistance > 0 ? "none" : "transform 0.2s",
|
|
96
98
|
pointerEvents: "none"
|
|
97
99
|
},
|
|
98
100
|
children: refreshing ? /* @__PURE__ */ jsx(LoadingIcon, { size: 20 }) : /* @__PURE__ */ jsx("svg", {
|
|
@@ -104,7 +106,7 @@ function PullToRefresh({ page, children }) {
|
|
|
104
106
|
strokeWidth: 2.5,
|
|
105
107
|
strokeLinecap: "round",
|
|
106
108
|
strokeLinejoin: "round",
|
|
107
|
-
style: { transform: `rotate(${
|
|
109
|
+
style: { transform: `rotate(${arrowTurn}deg)` },
|
|
108
110
|
children: /* @__PURE__ */ jsx("path", { d: "M12 5v14M6 13l6 6 6-6" })
|
|
109
111
|
})
|
|
110
112
|
}) : null]
|
package/dist/root.js
CHANGED
|
@@ -2,40 +2,53 @@ import { FONT_FAMILY, ThemeContext, resolveTheme, useTheme } from "./theme.js";
|
|
|
2
2
|
import { PortalContainerContext } from "./portal.js";
|
|
3
3
|
import { PageRoot } from "./page-root.js";
|
|
4
4
|
import { PullToRefresh } from "./pull-to-refresh.js";
|
|
5
|
+
import { mergeColors } from "@monimesl/dot-core";
|
|
5
6
|
import { useMemo, useState, useSyncExternalStore } from "react";
|
|
6
7
|
import { jsx } from "react/jsx-runtime";
|
|
7
8
|
//#region src/root.tsx
|
|
8
9
|
function Root({ page, dotContext, components, wrapper: Wrapper }) {
|
|
9
10
|
const theme = useSyncExternalStore(dotContext.theme.subscribe, dotContext.theme.get);
|
|
10
11
|
const systemContext = useSyncExternalStore(dotContext.systemContext.subscribe, dotContext.systemContext.get);
|
|
11
|
-
const
|
|
12
|
+
const pageColors = useSyncExternalStore(page.subscribeToColors, page.getColors);
|
|
13
|
+
const resolvedTheme = useMemo(() => resolveTheme(theme, systemContext.scheme, pageColors), [
|
|
14
|
+
theme,
|
|
15
|
+
systemContext.scheme,
|
|
16
|
+
pageColors
|
|
17
|
+
]);
|
|
12
18
|
const [rootElement, setRootElement] = useState(null);
|
|
13
|
-
const
|
|
19
|
+
const pageContent = /* @__PURE__ */ jsx(PageRoot, {
|
|
14
20
|
page,
|
|
15
21
|
components
|
|
16
22
|
});
|
|
17
23
|
return /* @__PURE__ */ jsx(ThemeContext.Provider, {
|
|
18
|
-
value:
|
|
24
|
+
value: resolvedTheme,
|
|
19
25
|
children: /* @__PURE__ */ jsx("div", {
|
|
20
26
|
ref: setRootElement,
|
|
21
27
|
className: "dot-theme-root",
|
|
22
|
-
"data-dot-scheme":
|
|
28
|
+
"data-dot-scheme": resolvedTheme.scheme,
|
|
23
29
|
children: /* @__PURE__ */ jsx(PortalContainerContext.Provider, {
|
|
24
30
|
value: rootElement,
|
|
25
31
|
children: /* @__PURE__ */ jsx(PullToRefresh, {
|
|
26
32
|
page,
|
|
27
33
|
children: Wrapper ? /* @__PURE__ */ jsx(Wrapper, {
|
|
28
|
-
theme:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
},
|
|
32
|
-
children: content
|
|
33
|
-
}) : /* @__PURE__ */ jsx(DefaultSurface, { children: content })
|
|
34
|
+
theme: withPageColors(theme, resolvedTheme.scheme, pageColors),
|
|
35
|
+
children: pageContent
|
|
36
|
+
}) : /* @__PURE__ */ jsx(DefaultSurface, { children: pageContent })
|
|
34
37
|
})
|
|
35
38
|
})
|
|
36
39
|
})
|
|
37
40
|
});
|
|
38
41
|
}
|
|
42
|
+
function withPageColors(theme, scheme, pageColors) {
|
|
43
|
+
return {
|
|
44
|
+
...theme,
|
|
45
|
+
scheme,
|
|
46
|
+
colors: {
|
|
47
|
+
...theme.colors,
|
|
48
|
+
...mergeColors(theme.colors ?? {}, pageColors)
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
39
52
|
function DefaultSurface({ children }) {
|
|
40
53
|
const { colors } = useTheme();
|
|
41
54
|
return /* @__PURE__ */ jsx("div", {
|
package/dist/theme.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ColorScheme, Theme, ThemeShape } from "@monimesl/dot-core";
|
|
1
|
+
import { ColorScheme, PageColors, Theme, ThemeShape } from "@monimesl/dot-core";
|
|
2
2
|
//#region src/theme.d.ts
|
|
3
3
|
export interface ResolvedColors {
|
|
4
4
|
primary: string;
|
|
@@ -21,6 +21,6 @@ export interface ResolvedTheme {
|
|
|
21
21
|
shape: ThemeShape;
|
|
22
22
|
radius: number;
|
|
23
23
|
}
|
|
24
|
-
export declare function resolveTheme(theme: Theme, systemScheme: ColorScheme): ResolvedTheme;
|
|
24
|
+
export declare function resolveTheme(theme: Theme, systemScheme: ColorScheme, pageColors?: PageColors): ResolvedTheme;
|
|
25
25
|
export declare function useTheme(): ResolvedTheme;
|
|
26
26
|
//#endregion
|
package/dist/theme.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { darken, mix } from "./color.js";
|
|
2
|
+
import { DEFAULT_BACKGROUND, READABLE_CONTRAST, contrast, isDark, pageBackground, textOn, themeScheme } from "@monimesl/dot-core";
|
|
2
3
|
import { createContext, useContext } from "react";
|
|
3
4
|
//#region src/theme.ts
|
|
4
5
|
const FONT_FAMILY = "system-ui, sans-serif";
|
|
@@ -11,7 +12,7 @@ const SHAPE_RADIUS = {
|
|
|
11
12
|
const DEFAULT_COLORS = {
|
|
12
13
|
light: {
|
|
13
14
|
primary: "#1c1c1e",
|
|
14
|
-
background:
|
|
15
|
+
background: DEFAULT_BACKGROUND.light,
|
|
15
16
|
surface: "#ffffff",
|
|
16
17
|
text: "#111111",
|
|
17
18
|
subtle: "#8e8e93",
|
|
@@ -24,7 +25,7 @@ const DEFAULT_COLORS = {
|
|
|
24
25
|
},
|
|
25
26
|
dark: {
|
|
26
27
|
primary: "#f5f5f5",
|
|
27
|
-
background:
|
|
28
|
+
background: DEFAULT_BACKGROUND.dark,
|
|
28
29
|
surface: "#1e1e1e",
|
|
29
30
|
text: "#f5f5f5",
|
|
30
31
|
subtle: "#8e8e93",
|
|
@@ -36,30 +37,64 @@ const DEFAULT_COLORS = {
|
|
|
36
37
|
danger: "#ff6961"
|
|
37
38
|
}
|
|
38
39
|
};
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const scheme = !theme.scheme || theme.scheme === "system" ? systemScheme : theme.scheme;
|
|
40
|
+
function resolveTheme(theme, systemScheme, pageColors = {}) {
|
|
41
|
+
const scheme = themeScheme(theme, systemScheme);
|
|
42
42
|
const defaults = DEFAULT_COLORS[scheme];
|
|
43
|
-
const
|
|
44
|
-
const
|
|
43
|
+
const themeColors = theme.colors ?? {};
|
|
44
|
+
const ownColor = (name) => pageColors[name]?.[scheme] ?? themeColors[name]?.[scheme];
|
|
45
45
|
const shape = theme.shape ?? "soft";
|
|
46
|
-
const
|
|
47
|
-
const
|
|
48
|
-
|
|
46
|
+
const background = pageBackground(pageColors.background, theme, systemScheme);
|
|
47
|
+
const onDashBackground = background === defaults.background;
|
|
48
|
+
let surfaces = defaults;
|
|
49
|
+
if (!onDashBackground) surfaces = surfacesOn(background);
|
|
50
|
+
const surface = ownColor("surface") ?? surfaces.surface;
|
|
51
|
+
const text = ownColor("text") ?? readableText(defaults.text, background);
|
|
52
|
+
let subtle = defaults.subtle;
|
|
53
|
+
if (!onDashBackground) subtle = quieterText(text, background, surface);
|
|
54
|
+
const primary = ownColor("primary") ?? defaults.primary;
|
|
49
55
|
return {
|
|
50
56
|
scheme,
|
|
51
57
|
colors: {
|
|
52
58
|
...defaults,
|
|
53
59
|
...primaryAndOnPrimary(primary, surface, text, scheme),
|
|
54
|
-
background
|
|
60
|
+
background,
|
|
55
61
|
surface,
|
|
56
|
-
text
|
|
62
|
+
text,
|
|
63
|
+
muted: ownColor("muted") ?? surfaces.muted,
|
|
64
|
+
border: ownColor("border") ?? surfaces.border,
|
|
65
|
+
subtle: ownColor("subtle") ?? subtle
|
|
57
66
|
},
|
|
58
|
-
customColors: resolveCustomColors(
|
|
67
|
+
customColors: resolveCustomColors(themeColors.custom ?? {}, scheme),
|
|
59
68
|
shape,
|
|
60
69
|
radius: SHAPE_RADIUS[shape]
|
|
61
70
|
};
|
|
62
71
|
}
|
|
72
|
+
function surfacesOn(background) {
|
|
73
|
+
if (isDark(background)) return {
|
|
74
|
+
surface: mix(background, "#ffffff", .08),
|
|
75
|
+
muted: mix(background, "#ffffff", .14),
|
|
76
|
+
border: mix(background, "#ffffff", .16)
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
surface: mix(background, "#ffffff", .75),
|
|
80
|
+
muted: mix(background, "#000000", .06),
|
|
81
|
+
border: mix(background, "#000000", .1)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const QUIET_CONTRAST = 3;
|
|
85
|
+
function quieterText(text, background, surface) {
|
|
86
|
+
for (let shareOfBackground = .5; shareOfBackground > 0; shareOfBackground -= .05) {
|
|
87
|
+
const quieter = mix(text, background, shareOfBackground);
|
|
88
|
+
const readsOnBackground = contrast(quieter, background) >= QUIET_CONTRAST;
|
|
89
|
+
const readsOnSurface = contrast(quieter, surface) >= QUIET_CONTRAST;
|
|
90
|
+
if (readsOnBackground && readsOnSurface) return quieter;
|
|
91
|
+
}
|
|
92
|
+
return text;
|
|
93
|
+
}
|
|
94
|
+
function readableText(text, background) {
|
|
95
|
+
if (contrast(text, background) >= READABLE_CONTRAST) return text;
|
|
96
|
+
return textOn(background);
|
|
97
|
+
}
|
|
63
98
|
function resolveCustomColors(custom, scheme) {
|
|
64
99
|
const resolved = {};
|
|
65
100
|
for (const [name, color] of Object.entries(custom)) {
|
|
@@ -68,14 +103,15 @@ function resolveCustomColors(custom, scheme) {
|
|
|
68
103
|
}
|
|
69
104
|
return resolved;
|
|
70
105
|
}
|
|
106
|
+
const MOST_DARKENING = 15;
|
|
71
107
|
function primaryAndOnPrimary(primary, surface, text, scheme) {
|
|
72
|
-
if (contrast(primary, surface) >=
|
|
108
|
+
if (contrast(primary, surface) >= READABLE_CONTRAST) return {
|
|
73
109
|
primary,
|
|
74
110
|
onPrimary: surface
|
|
75
111
|
};
|
|
76
112
|
if (scheme === "light") for (let points = .5; points <= MOST_DARKENING; points += .5) {
|
|
77
113
|
const darker = darken(primary, points);
|
|
78
|
-
if (contrast(darker, surface) >=
|
|
114
|
+
if (contrast(darker, surface) >= READABLE_CONTRAST) return {
|
|
79
115
|
primary: darker,
|
|
80
116
|
onPrimary: surface
|
|
81
117
|
};
|