@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
package/README.md
CHANGED
|
@@ -21,9 +21,11 @@ source at build time, from `@phosphor-icons/core`.
|
|
|
21
21
|
## The theme
|
|
22
22
|
|
|
23
23
|
A dot sets `scheme`, `colors` and `shape` in `defineDot`. The colors are `primary`, `background`,
|
|
24
|
-
`surface` and `
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
`surface`, `text`, `muted`, `border` and `subtle`, each for light and dark, and `custom` for the
|
|
25
|
+
dot's own named colors. A page can set its own colors over the theme's, with `configs.colors` or
|
|
26
|
+
`setColors`. The renderer fills in the rest of the palette from Dash's own look. On a background
|
|
27
|
+
that isn't Dash's, it works out surfaces and quieter text that sit well on it. `useTheme()` gives a
|
|
28
|
+
component the resolved theme.
|
|
27
29
|
|
|
28
30
|
## Only the components a dot uses
|
|
29
31
|
|
package/dist/color.js
CHANGED
|
@@ -1,25 +1,12 @@
|
|
|
1
1
|
//#region src/color.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const secondLuminance = luminance(second);
|
|
6
|
-
const lighter = Math.max(firstLuminance, secondLuminance);
|
|
7
|
-
const darker = Math.min(firstLuminance, secondLuminance);
|
|
8
|
-
return (lighter + .05) / (darker + .05);
|
|
2
|
+
function mix(from, to, amount) {
|
|
3
|
+
const end = channels(to);
|
|
4
|
+
return toHex(channels(from).map((start, index) => start + (end[index] - start) * amount));
|
|
9
5
|
}
|
|
10
6
|
function darken(color, points) {
|
|
11
7
|
const [hue, saturation, lightness] = toHsl(channels(color));
|
|
12
8
|
return toHex(fromHsl(hue, saturation, Math.max(0, lightness - points / 100)));
|
|
13
9
|
}
|
|
14
|
-
function luminance(color) {
|
|
15
|
-
const [red, green, blue] = channels(color).map(linearLight);
|
|
16
|
-
return .2126 * red + .7152 * green + .0722 * blue;
|
|
17
|
-
}
|
|
18
|
-
function linearLight(channel) {
|
|
19
|
-
const share = channel / 255;
|
|
20
|
-
if (share <= .03928) return share / 12.92;
|
|
21
|
-
return ((share + .055) / 1.055) ** 2.4;
|
|
22
|
-
}
|
|
23
10
|
function channels(color) {
|
|
24
11
|
let hex = color.slice(1);
|
|
25
12
|
if (hex.length === 3 || hex.length === 4) hex = [...hex].map((digit) => digit + digit).join("");
|
|
@@ -27,7 +14,7 @@ function channels(color) {
|
|
|
27
14
|
0,
|
|
28
15
|
2,
|
|
29
16
|
4
|
|
30
|
-
].map((
|
|
17
|
+
].map((offset) => parseInt(hex.slice(offset, offset + 2), 16));
|
|
31
18
|
return [
|
|
32
19
|
red,
|
|
33
20
|
green,
|
|
@@ -104,4 +91,4 @@ function fromHsl(hue, saturation, lightness) {
|
|
|
104
91
|
];
|
|
105
92
|
}
|
|
106
93
|
//#endregion
|
|
107
|
-
export {
|
|
94
|
+
export { darken, mix };
|
|
@@ -12,8 +12,8 @@ const AmountInput$1 = ({ value, currency = DEFAULT_CURRENCY, minorUnits, unit =
|
|
|
12
12
|
const { colors } = useTheme();
|
|
13
13
|
const decimalPlaces = minorUnits === void 0 ? currencyMinorUnits(currency) : Math.max(0, Math.round(minorUnits));
|
|
14
14
|
const scale = unit === "major" ? 10 ** decimalPlaces : 1;
|
|
15
|
-
const
|
|
16
|
-
const [text, typeText, reshowText] = useTypedText(amountText(value, scale), onChange !== void 0, (sent) => sent === "" ? "" :
|
|
15
|
+
const formatAmount = (minor) => formatMinorUnits(minor, decimalPlaces);
|
|
16
|
+
const [text, typeText, reshowText] = useTypedText(amountText(value, scale), onChange !== void 0, (sent) => sent === "" ? "" : formatAmount(Number(sent)));
|
|
17
17
|
const box = useFieldBox(error, disabled);
|
|
18
18
|
const { noteId, controlAttributes } = useFieldNote(hint, error);
|
|
19
19
|
return /* @__PURE__ */ jsx(Field, {
|
|
@@ -39,7 +39,7 @@ const AmountInput$1 = ({ value, currency = DEFAULT_CURRENCY, minorUnits, unit =
|
|
|
39
39
|
children: currency
|
|
40
40
|
}) : null, /* @__PURE__ */ jsx("input", {
|
|
41
41
|
value: text,
|
|
42
|
-
placeholder: placeholder ??
|
|
42
|
+
placeholder: placeholder ?? formatAmount(0),
|
|
43
43
|
inputMode: decimalPlaces > 0 ? "decimal" : "numeric",
|
|
44
44
|
disabled,
|
|
45
45
|
...controlAttributes,
|
|
@@ -47,7 +47,7 @@ const AmountInput$1 = ({ value, currency = DEFAULT_CURRENCY, minorUnits, unit =
|
|
|
47
47
|
onBlur: () => {
|
|
48
48
|
box.onBlur();
|
|
49
49
|
const amount = toMinorUnits(text, decimalPlaces);
|
|
50
|
-
if (amount !== null) reshowText(
|
|
50
|
+
if (amount !== null) reshowText(formatAmount(amount));
|
|
51
51
|
},
|
|
52
52
|
onChange: (event) => {
|
|
53
53
|
const typed = cleanAmount(event.currentTarget.value, decimalPlaces);
|
|
@@ -81,10 +81,12 @@ function amountText(value, scale) {
|
|
|
81
81
|
}
|
|
82
82
|
function cleanAmount(typed, decimalPlaces) {
|
|
83
83
|
const [whole = "", ...fractions] = typed.replace(/[^\d.]/g, "").split(".");
|
|
84
|
-
|
|
85
|
-
if (
|
|
84
|
+
let wholeDigits = whole.replace(/^0+/, "");
|
|
85
|
+
if (wholeDigits === "" && whole !== "") wholeDigits = "0";
|
|
86
|
+
if (decimalPlaces === 0 || fractions.length === 0) return groupThousands(wholeDigits);
|
|
87
|
+
if (wholeDigits === "") wholeDigits = "0";
|
|
86
88
|
const fraction = fractions.join("").slice(0, decimalPlaces);
|
|
87
|
-
return `${groupThousands(
|
|
89
|
+
return `${groupThousands(wholeDigits)}.${fraction}`;
|
|
88
90
|
}
|
|
89
91
|
function toMinorUnits(text, decimalPlaces) {
|
|
90
92
|
const plain = text.replaceAll(",", "");
|
|
@@ -13,18 +13,23 @@ const AVATAR_SIZE = {
|
|
|
13
13
|
function initials(name) {
|
|
14
14
|
const words = name.trim().split(/\s+/).filter(Boolean);
|
|
15
15
|
if (words.length === 0) return "";
|
|
16
|
-
|
|
16
|
+
const firstInitial = initialOf(words[0]);
|
|
17
|
+
if (words.length === 1) return firstInitial;
|
|
18
|
+
return firstInitial + initialOf(words[words.length - 1]);
|
|
19
|
+
}
|
|
20
|
+
function initialOf(word) {
|
|
21
|
+
return word.charAt(0).toUpperCase();
|
|
17
22
|
}
|
|
18
23
|
const Avatar = ({ name = "", image, size = "medium" }) => {
|
|
19
24
|
const { colors } = useTheme();
|
|
20
|
-
const [
|
|
25
|
+
const [failedImage, setFailedImage] = useState();
|
|
21
26
|
const pixels = AVATAR_SIZE[size];
|
|
22
27
|
const letters = initials(name);
|
|
23
28
|
let content;
|
|
24
|
-
if (image &&
|
|
29
|
+
if (image && failedImage !== image) content = /* @__PURE__ */ jsx("img", {
|
|
25
30
|
src: image,
|
|
26
31
|
alt: "",
|
|
27
|
-
onError: () =>
|
|
32
|
+
onError: () => setFailedImage(image),
|
|
28
33
|
style: {
|
|
29
34
|
width: "100%",
|
|
30
35
|
height: "100%",
|
package/dist/components/box.js
CHANGED
|
@@ -16,10 +16,8 @@ function boxStyle(props, theme, look = {}) {
|
|
|
16
16
|
const radius = props.radius ?? look.radius;
|
|
17
17
|
const style = {};
|
|
18
18
|
if (background !== void 0) style.background = backgroundColor(background, theme);
|
|
19
|
-
if (border
|
|
20
|
-
|
|
21
|
-
style.border = border === "none" ? "none" : `1px solid ${color}`;
|
|
22
|
-
}
|
|
19
|
+
if (border === "none") style.border = "none";
|
|
20
|
+
else if (border !== void 0) style.border = `1px solid ${border === "strong" ? theme.colors.subtle : theme.colors.border}`;
|
|
23
21
|
if (radius !== void 0) {
|
|
24
22
|
style.borderRadius = radius === "full" ? FULL_RADIUS : theme.radius * RADIUS_SCALE[radius];
|
|
25
23
|
style.overflow = "hidden";
|
|
@@ -42,6 +40,7 @@ function backgroundColor(background, theme) {
|
|
|
42
40
|
if (BACKGROUND_WORDS.has(background)) return theme.colors[background];
|
|
43
41
|
return customColor(background, theme);
|
|
44
42
|
}
|
|
43
|
+
const unknownColors = /* @__PURE__ */ new Set();
|
|
45
44
|
function customColor(name, theme) {
|
|
46
45
|
const color = theme.customColors[name];
|
|
47
46
|
if (color === void 0 && !unknownColors.has(name)) {
|
|
@@ -50,7 +49,6 @@ function customColor(name, theme) {
|
|
|
50
49
|
}
|
|
51
50
|
return color;
|
|
52
51
|
}
|
|
53
|
-
const unknownColors = /* @__PURE__ */ new Set();
|
|
54
52
|
function cssLength(value) {
|
|
55
53
|
return value === "fill" ? "100%" : value;
|
|
56
54
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useTheme } from "../theme.js";
|
|
2
2
|
import { SPACE } from "./tokens.js";
|
|
3
|
+
import { clamp } from "./numbers.js";
|
|
3
4
|
import { paddingStyle } from "./padding.js";
|
|
4
|
-
import { clamp } from "./utils.js";
|
|
5
5
|
import { createEvent } from "@monimesl/dot-core";
|
|
6
6
|
import { Children, Fragment, isValidElement, useEffect, useEffectEvent, useRef, useState } from "react";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -17,41 +17,41 @@ const Carousel$1 = ({ autoplay = false, interval = 4e3, loop = false, indicator
|
|
|
17
17
|
const slides = slidesOf(children);
|
|
18
18
|
const count = slides.length;
|
|
19
19
|
const looping = loop && count > 1;
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const [position, setPosition] = useState(() =>
|
|
20
|
+
const firstPosition = looping ? 1 : 0;
|
|
21
|
+
const lastPosition = looping ? count + 1 : count - 1;
|
|
22
|
+
const [position, setPosition] = useState(() => firstPosition + slideIndex(index ?? 0, count));
|
|
23
23
|
const [animated, setAnimated] = useState(true);
|
|
24
|
-
const [
|
|
24
|
+
const [dragOffset, setDragOffset] = useState(0);
|
|
25
25
|
const [dragging, setDragging] = useState(false);
|
|
26
|
-
const [
|
|
26
|
+
const [viewportWidth, setViewportWidth] = useState(0);
|
|
27
27
|
const [previousIndex, setPreviousIndex] = useState(index);
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
28
|
+
const viewportRef = useRef(null);
|
|
29
|
+
const gestureRef = useRef(null);
|
|
30
|
+
const ignoreNextClick = useRef(false);
|
|
31
31
|
if (index !== previousIndex) {
|
|
32
32
|
setPreviousIndex(index);
|
|
33
33
|
if (index !== void 0) {
|
|
34
34
|
setAnimated(true);
|
|
35
|
-
setPosition(
|
|
35
|
+
setPosition(firstPosition + slideIndex(index, count));
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const moveTo = (
|
|
41
|
-
const
|
|
38
|
+
const shownPosition = clamp(position, 0, lastPosition);
|
|
39
|
+
const currentIndex = count === 0 ? 0 : wrapIndex(shownPosition - firstPosition, count);
|
|
40
|
+
const moveTo = (targetPosition) => {
|
|
41
|
+
const nextPosition = clamp(targetPosition, 0, lastPosition);
|
|
42
42
|
setAnimated(true);
|
|
43
|
-
setPosition(
|
|
44
|
-
const nextIndex =
|
|
45
|
-
if (nextIndex !==
|
|
43
|
+
setPosition(nextPosition);
|
|
44
|
+
const nextIndex = wrapIndex(nextPosition - firstPosition, count);
|
|
45
|
+
if (nextIndex !== currentIndex) onChange?.(createEvent("change", { index: nextIndex }));
|
|
46
46
|
};
|
|
47
|
-
const
|
|
48
|
-
const beyondEnd =
|
|
49
|
-
if (!looping && beyondEnd) moveTo(
|
|
50
|
-
else moveTo(
|
|
47
|
+
const stepBy = (direction) => {
|
|
48
|
+
const beyondEnd = currentIndex + direction < 0 || currentIndex + direction >= count;
|
|
49
|
+
if (!looping && beyondEnd) moveTo(shownPosition);
|
|
50
|
+
else moveTo(shownPosition + direction);
|
|
51
51
|
};
|
|
52
52
|
const advance = useEffectEvent(() => {
|
|
53
|
-
if (!looping &&
|
|
54
|
-
else moveTo(
|
|
53
|
+
if (!looping && currentIndex === count - 1) moveTo(firstPosition);
|
|
54
|
+
else moveTo(shownPosition + 1);
|
|
55
55
|
});
|
|
56
56
|
useEffect(() => {
|
|
57
57
|
if (!autoplay || count < 2 || dragging) return;
|
|
@@ -62,10 +62,11 @@ const Carousel$1 = ({ autoplay = false, interval = 4e3, loop = false, indicator
|
|
|
62
62
|
count,
|
|
63
63
|
dragging,
|
|
64
64
|
interval,
|
|
65
|
-
|
|
65
|
+
currentIndex
|
|
66
66
|
]);
|
|
67
67
|
useEffect(() => {
|
|
68
|
-
|
|
68
|
+
const onCopy = position === 0 || position === count + 1;
|
|
69
|
+
if (!looping || !onCopy) return;
|
|
69
70
|
const timer = setTimeout(() => {
|
|
70
71
|
setAnimated(false);
|
|
71
72
|
setPosition(position === 0 ? count : 1);
|
|
@@ -77,27 +78,27 @@ const Carousel$1 = ({ autoplay = false, interval = 4e3, loop = false, indicator
|
|
|
77
78
|
count
|
|
78
79
|
]);
|
|
79
80
|
const gestureOf = (event) => {
|
|
80
|
-
const inProgress =
|
|
81
|
+
const inProgress = gestureRef.current;
|
|
81
82
|
return inProgress?.pointerId === event.pointerId ? inProgress : null;
|
|
82
83
|
};
|
|
83
84
|
const endGesture = () => {
|
|
84
|
-
|
|
85
|
+
gestureRef.current = null;
|
|
85
86
|
setDragging(false);
|
|
86
|
-
|
|
87
|
+
setDragOffset(0);
|
|
87
88
|
setAnimated(true);
|
|
88
89
|
};
|
|
89
90
|
const onPointerDown = (event) => {
|
|
90
91
|
if (count < 2 || !event.isPrimary) return;
|
|
91
|
-
|
|
92
|
+
gestureRef.current = {
|
|
92
93
|
pointerId: event.pointerId,
|
|
93
94
|
startX: event.clientX,
|
|
94
95
|
startY: event.clientY,
|
|
95
96
|
startTime: event.timeStamp,
|
|
96
97
|
swiping: false
|
|
97
98
|
};
|
|
98
|
-
|
|
99
|
+
ignoreNextClick.current = false;
|
|
99
100
|
setDragging(true);
|
|
100
|
-
|
|
101
|
+
setViewportWidth(viewportRef.current?.clientWidth ?? 0);
|
|
101
102
|
};
|
|
102
103
|
const onPointerMove = (event) => {
|
|
103
104
|
const swipe = gestureOf(event);
|
|
@@ -111,13 +112,14 @@ const Carousel$1 = ({ autoplay = false, interval = 4e3, loop = false, indicator
|
|
|
111
112
|
return;
|
|
112
113
|
}
|
|
113
114
|
swipe.swiping = true;
|
|
114
|
-
|
|
115
|
+
ignoreNextClick.current = true;
|
|
115
116
|
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
116
117
|
setAnimated(false);
|
|
117
118
|
}
|
|
118
|
-
const beforeFirst =
|
|
119
|
-
const afterLast =
|
|
120
|
-
|
|
119
|
+
const beforeFirst = currentIndex === 0 && movedX > 0;
|
|
120
|
+
const afterLast = currentIndex === count - 1 && movedX < 0;
|
|
121
|
+
if (!looping && (beforeFirst || afterLast)) setDragOffset(movedX * EDGE_RESISTANCE);
|
|
122
|
+
else setDragOffset(movedX);
|
|
121
123
|
};
|
|
122
124
|
const onPointerUp = (event) => {
|
|
123
125
|
const swipe = gestureOf(event);
|
|
@@ -126,13 +128,15 @@ const Carousel$1 = ({ autoplay = false, interval = 4e3, loop = false, indicator
|
|
|
126
128
|
if (!swipe.swiping) return;
|
|
127
129
|
const movedX = event.clientX - swipe.startX;
|
|
128
130
|
const speed = Math.abs(movedX) / Math.max(1, event.timeStamp - swipe.startTime);
|
|
129
|
-
if (Math.abs(movedX) >
|
|
130
|
-
else moveTo(
|
|
131
|
+
if (Math.abs(movedX) > viewportWidth * SWIPE_DISTANCE || speed > SWIPE_SPEED) stepBy(movedX < 0 ? 1 : -1);
|
|
132
|
+
else moveTo(shownPosition);
|
|
131
133
|
};
|
|
132
134
|
const gapWidth = SPACE[gap];
|
|
133
135
|
const transition = animated ? `transform ${SLIDE_DURATION}ms ${SLIDE_EASING}` : "none";
|
|
134
|
-
|
|
135
|
-
|
|
136
|
+
let draggedSlides = 0;
|
|
137
|
+
if (viewportWidth > 0) draggedSlides = dragOffset / (viewportWidth + gapWidth);
|
|
138
|
+
let track = slides;
|
|
139
|
+
if (looping) track = [
|
|
136
140
|
{
|
|
137
141
|
...slides[count - 1],
|
|
138
142
|
key: "copy-of-last"
|
|
@@ -142,7 +146,7 @@ const Carousel$1 = ({ autoplay = false, interval = 4e3, loop = false, indicator
|
|
|
142
146
|
...slides[0],
|
|
143
147
|
key: "copy-of-first"
|
|
144
148
|
}
|
|
145
|
-
]
|
|
149
|
+
];
|
|
146
150
|
return /* @__PURE__ */ jsxs("div", {
|
|
147
151
|
className: "dot-carousel",
|
|
148
152
|
role: "region",
|
|
@@ -155,15 +159,15 @@ const Carousel$1 = ({ autoplay = false, interval = 4e3, loop = false, indicator
|
|
|
155
159
|
...paddingStyle(padding)
|
|
156
160
|
},
|
|
157
161
|
children: [/* @__PURE__ */ jsx("div", {
|
|
158
|
-
ref:
|
|
162
|
+
ref: viewportRef,
|
|
159
163
|
onPointerDown,
|
|
160
164
|
onPointerMove,
|
|
161
165
|
onPointerUp,
|
|
162
166
|
onPointerCancel: endGesture,
|
|
163
167
|
onDragStart: (event) => event.preventDefault(),
|
|
164
168
|
onClickCapture: (event) => {
|
|
165
|
-
if (
|
|
166
|
-
|
|
169
|
+
if (ignoreNextClick.current) {
|
|
170
|
+
ignoreNextClick.current = false;
|
|
167
171
|
event.stopPropagation();
|
|
168
172
|
}
|
|
169
173
|
},
|
|
@@ -176,17 +180,17 @@ const Carousel$1 = ({ autoplay = false, interval = 4e3, loop = false, indicator
|
|
|
176
180
|
style: {
|
|
177
181
|
display: "flex",
|
|
178
182
|
gap: gapWidth,
|
|
179
|
-
transform: `translateX(calc(${-
|
|
183
|
+
transform: `translateX(calc(${-shownPosition} * (100% + ${gapWidth}px) + ${dragOffset}px))`,
|
|
180
184
|
transition
|
|
181
185
|
},
|
|
182
186
|
children: track.map((slide, trackPosition) => {
|
|
183
|
-
const visible = trackPosition ===
|
|
184
|
-
const distance = Math.abs(trackPosition -
|
|
187
|
+
const visible = trackPosition === shownPosition;
|
|
188
|
+
const distance = Math.abs(trackPosition - shownPosition + draggedSlides);
|
|
185
189
|
const scale = 1 - Math.min(distance, 1) * .15000000000000002;
|
|
186
190
|
return /* @__PURE__ */ jsx("div", {
|
|
187
191
|
role: "group",
|
|
188
192
|
"aria-roledescription": "slide",
|
|
189
|
-
"aria-label": `${
|
|
193
|
+
"aria-label": `${wrapIndex(trackPosition - firstPosition, count) + 1} of ${count}`,
|
|
190
194
|
"aria-hidden": !visible,
|
|
191
195
|
inert: !visible,
|
|
192
196
|
style: {
|
|
@@ -205,13 +209,13 @@ const Carousel$1 = ({ autoplay = false, interval = 4e3, loop = false, indicator
|
|
|
205
209
|
display: "flex",
|
|
206
210
|
justifyContent: "center"
|
|
207
211
|
},
|
|
208
|
-
children: slides.map((slide,
|
|
209
|
-
const active =
|
|
212
|
+
children: slides.map((slide, dotIndex) => {
|
|
213
|
+
const active = dotIndex === currentIndex;
|
|
210
214
|
return /* @__PURE__ */ jsx("button", {
|
|
211
215
|
type: "button",
|
|
212
|
-
"aria-label": `Slide ${
|
|
216
|
+
"aria-label": `Slide ${dotIndex + 1} of ${count}`,
|
|
213
217
|
"aria-current": active,
|
|
214
|
-
onClick: () => moveTo(
|
|
218
|
+
onClick: () => moveTo(firstPosition + dotIndex),
|
|
215
219
|
style: {
|
|
216
220
|
padding: "6px 3px",
|
|
217
221
|
border: "none",
|
|
@@ -247,7 +251,7 @@ function slidesOf(children, keyPrefix = "") {
|
|
|
247
251
|
function slideIndex(index, count) {
|
|
248
252
|
return clamp(Math.round(index), 0, count - 1);
|
|
249
253
|
}
|
|
250
|
-
function
|
|
254
|
+
function wrapIndex(value, count) {
|
|
251
255
|
return (value % count + count) % count;
|
|
252
256
|
}
|
|
253
257
|
//#endregion
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { useTheme } from "../theme.js";
|
|
2
|
-
import { DISABLED_OPACITY, SPACE, WEIGHTS } from "./tokens.js";
|
|
2
|
+
import { CENTERED, DISABLED_OPACITY, SPACE, WEIGHTS } from "./tokens.js";
|
|
3
3
|
import { Field } from "./field.js";
|
|
4
4
|
import { fieldBorderColor, useFieldNote } from "./field-box.js";
|
|
5
5
|
import { useTypedText } from "./typed-text.js";
|
|
6
|
+
import { wholeCount } from "./numbers.js";
|
|
6
7
|
import { createEvent } from "@monimesl/dot-core";
|
|
7
8
|
import { useState } from "react";
|
|
8
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -12,17 +13,15 @@ const CodeInput$1 = ({ value, length = 6, label, hint, error, secure, disabled,
|
|
|
12
13
|
const [text, typeText] = useTypedText(value, onChange !== void 0);
|
|
13
14
|
const [focused, setFocused] = useState(false);
|
|
14
15
|
const { noteId, controlAttributes } = useFieldNote(hint, error);
|
|
15
|
-
const count =
|
|
16
|
+
const count = wholeCount(length);
|
|
16
17
|
const digits = text.slice(0, count);
|
|
17
|
-
const
|
|
18
|
+
const nextBox = Math.min(digits.length, count - 1);
|
|
18
19
|
const boxes = Array.from({ length: count }, (_, index) => {
|
|
19
20
|
const digit = digits[index];
|
|
20
|
-
const borderColor = fieldBorderColor(colors, error, focused && index ===
|
|
21
|
+
const borderColor = fieldBorderColor(colors, error, focused && index === nextBox);
|
|
21
22
|
return /* @__PURE__ */ jsx("span", {
|
|
22
23
|
style: {
|
|
23
|
-
|
|
24
|
-
alignItems: "center",
|
|
25
|
-
justifyContent: "center",
|
|
24
|
+
...CENTERED,
|
|
26
25
|
flex: "1 1 0",
|
|
27
26
|
maxWidth: 52,
|
|
28
27
|
height: 52,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useTheme } from "../theme.js";
|
|
2
|
-
import { FONT_SIZE, ICON_SIZE, SPACE, WEIGHTS } from "./tokens.js";
|
|
2
|
+
import { CENTERED, FONT_SIZE, ICON_SIZE, SPACE, WEIGHTS } from "./tokens.js";
|
|
3
3
|
import { insets, paddingStyle } from "./padding.js";
|
|
4
4
|
import { IconGraphic } from "./icon.js";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -20,9 +20,7 @@ const EmptyState = ({ icon, title, text, children, ...padding }) => {
|
|
|
20
20
|
children: [
|
|
21
21
|
icon ? /* @__PURE__ */ jsx("span", {
|
|
22
22
|
style: {
|
|
23
|
-
|
|
24
|
-
alignItems: "center",
|
|
25
|
-
justifyContent: "center",
|
|
23
|
+
...CENTERED,
|
|
26
24
|
width: 64,
|
|
27
25
|
height: 64,
|
|
28
26
|
borderRadius: "50%",
|
|
@@ -2,8 +2,8 @@ import { useTheme } from "../theme.js";
|
|
|
2
2
|
import { FONT_SIZE, ICON_SIZE, SPACE, WEIGHTS } from "./tokens.js";
|
|
3
3
|
import { CLOSE_ARTWORK } from "./icon-artwork.js";
|
|
4
4
|
import { IconSvg } from "./icon-svg.js";
|
|
5
|
+
import { clamp } from "./numbers.js";
|
|
5
6
|
import { insets, paddingStyle } from "./padding.js";
|
|
6
|
-
import { clamp } from "./utils.js";
|
|
7
7
|
import { STATUS_ARTWORK, toneBackground, toneColor } from "./tones.js";
|
|
8
8
|
import { IconButton } from "./icon-button.js";
|
|
9
9
|
import { createEvent } from "@monimesl/dot-core";
|
package/dist/components/grid.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useTheme } from "../theme.js";
|
|
2
|
-
import { CARD_RADIUS_SCALE, FONT_SIZE, PILL_STYLE, SPACE } from "./tokens.js";
|
|
2
|
+
import { CARD_RADIUS_SCALE, CENTERED, FONT_SIZE, PILL_STYLE, SPACE } from "./tokens.js";
|
|
3
|
+
import { wholeCount } from "./numbers.js";
|
|
3
4
|
import { paddingStyle } from "./padding.js";
|
|
4
5
|
import { IconGraphic } from "./icon.js";
|
|
5
6
|
import { pressable } from "./pressable.js";
|
|
@@ -11,7 +12,7 @@ const Grid$1 = ({ columns = 4, gap = "medium", children, ...padding }) => /* @__
|
|
|
11
12
|
className: "dot-grid",
|
|
12
13
|
style: {
|
|
13
14
|
display: "grid",
|
|
14
|
-
gridTemplateColumns: `repeat(${
|
|
15
|
+
gridTemplateColumns: `repeat(${wholeCount(columns)}, minmax(0, 1fr))`,
|
|
15
16
|
gap: SPACE[gap],
|
|
16
17
|
...paddingStyle(padding)
|
|
17
18
|
},
|
|
@@ -54,9 +55,7 @@ const GridItem$1 = ({ label, icon, image, badge, onTap }) => {
|
|
|
54
55
|
children: [/* @__PURE__ */ jsxs("span", {
|
|
55
56
|
style: {
|
|
56
57
|
position: "relative",
|
|
57
|
-
|
|
58
|
-
alignItems: "center",
|
|
59
|
-
justifyContent: "center",
|
|
58
|
+
...CENTERED,
|
|
60
59
|
flexShrink: 0,
|
|
61
60
|
width: TILE_SIZE,
|
|
62
61
|
height: TILE_SIZE,
|
package/dist/components/list.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useTheme } from "../theme.js";
|
|
2
|
-
import { CARD_RADIUS_SCALE, FONT_SIZE, ICON_SIZE, WEIGHTS } from "./tokens.js";
|
|
2
|
+
import { CARD_RADIUS_SCALE, CENTERED, FONT_SIZE, ICON_SIZE, WEIGHTS } from "./tokens.js";
|
|
3
3
|
import { CHEVRON_RIGHT_ARTWORK } from "./icon-artwork.js";
|
|
4
4
|
import { IconSvg } from "./icon-svg.js";
|
|
5
5
|
import { insets, paddingStyle } from "./padding.js";
|
|
@@ -11,22 +11,22 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
|
11
11
|
const END_MARGIN = "0px 0px 200px 0px";
|
|
12
12
|
const List$1 = ({ onEndReached, children, ...padding }) => {
|
|
13
13
|
const { colors, radius } = useTheme();
|
|
14
|
-
const
|
|
15
|
-
const
|
|
14
|
+
const listRef = useRef(null);
|
|
15
|
+
const lastRowReached = useRef(null);
|
|
16
16
|
useEffect(() => {
|
|
17
|
-
const
|
|
18
|
-
if (!onEndReached || !
|
|
17
|
+
const lastRow = listRef.current?.lastElementChild;
|
|
18
|
+
if (!onEndReached || !lastRow || typeof IntersectionObserver === "undefined") return;
|
|
19
19
|
const observer = new IntersectionObserver((entries) => {
|
|
20
|
-
if (entries.some((entry) => entry.isIntersecting) &&
|
|
21
|
-
|
|
20
|
+
if (entries.some((entry) => entry.isIntersecting) && lastRowReached.current !== lastRow) {
|
|
21
|
+
lastRowReached.current = lastRow;
|
|
22
22
|
onEndReached(createEvent("endReached"));
|
|
23
23
|
}
|
|
24
24
|
}, { rootMargin: END_MARGIN });
|
|
25
|
-
observer.observe(
|
|
25
|
+
observer.observe(lastRow);
|
|
26
26
|
return () => observer.disconnect();
|
|
27
27
|
});
|
|
28
28
|
return /* @__PURE__ */ jsx("ul", {
|
|
29
|
-
ref:
|
|
29
|
+
ref: listRef,
|
|
30
30
|
className: "dot-list",
|
|
31
31
|
style: {
|
|
32
32
|
display: "flex",
|
|
@@ -59,9 +59,7 @@ const ListItem$1 = ({ title, subtitle, value, icon, image, onTap, children, ...p
|
|
|
59
59
|
});
|
|
60
60
|
else if (icon) leading = /* @__PURE__ */ jsx("span", {
|
|
61
61
|
style: {
|
|
62
|
-
|
|
63
|
-
alignItems: "center",
|
|
64
|
-
justifyContent: "center",
|
|
62
|
+
...CENTERED,
|
|
65
63
|
width: 36,
|
|
66
64
|
height: 36,
|
|
67
65
|
borderRadius: "50%",
|
|
@@ -14,14 +14,17 @@ function insets(block, inline = block) {
|
|
|
14
14
|
bottom: block
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
|
-
function paddingStyle(props,
|
|
18
|
-
const side = (space, pixels) => space === void 0 ? pixels : SPACE[space];
|
|
17
|
+
function paddingStyle(props, ownInsets = NO_INSETS) {
|
|
19
18
|
return {
|
|
20
|
-
paddingTop:
|
|
21
|
-
paddingInlineStart:
|
|
22
|
-
paddingInlineEnd:
|
|
23
|
-
paddingBottom:
|
|
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)
|
|
24
23
|
};
|
|
25
24
|
}
|
|
25
|
+
function sidePadding(pageSpace, ownPixels) {
|
|
26
|
+
if (pageSpace === void 0) return ownPixels;
|
|
27
|
+
return SPACE[pageSpace];
|
|
28
|
+
}
|
|
26
29
|
//#endregion
|
|
27
30
|
export { insets, paddingStyle };
|
|
@@ -6,13 +6,13 @@ import { jsx } from "react/jsx-runtime";
|
|
|
6
6
|
//#region src/components/scroll.tsx
|
|
7
7
|
const REST_DELAY_MS = 120;
|
|
8
8
|
const Scroll$1 = ({ gap = "medium", snap = "none", index, onChange, children, ...padding }) => {
|
|
9
|
-
const
|
|
9
|
+
const rowRef = useRef(null);
|
|
10
10
|
const reportedIndex = useRef(void 0);
|
|
11
11
|
const restTimer = useRef(void 0);
|
|
12
12
|
const paddingCss = paddingStyle(padding);
|
|
13
13
|
const startPadding = Number(paddingCss.paddingInlineStart);
|
|
14
14
|
useEffect(() => {
|
|
15
|
-
const element =
|
|
15
|
+
const element = rowRef.current;
|
|
16
16
|
if (index === void 0 || index === reportedIndex.current || !element) return;
|
|
17
17
|
const child = element.children[index];
|
|
18
18
|
if (child) {
|
|
@@ -23,20 +23,22 @@ const Scroll$1 = ({ gap = "medium", snap = "none", index, onChange, children, ..
|
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
25
|
}, [index, startPadding]);
|
|
26
|
-
useEffect(() =>
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
return () => clearTimeout(restTimer.current);
|
|
28
|
+
}, []);
|
|
27
29
|
return /* @__PURE__ */ jsx("div", {
|
|
28
|
-
ref:
|
|
30
|
+
ref: rowRef,
|
|
29
31
|
className: "dot-scroll",
|
|
30
32
|
onScroll: onChange ? () => {
|
|
31
33
|
clearTimeout(restTimer.current);
|
|
32
34
|
restTimer.current = setTimeout(() => {
|
|
33
|
-
const element =
|
|
35
|
+
const element = rowRef.current;
|
|
34
36
|
if (!element) return;
|
|
35
37
|
const visibleStart = element.scrollLeft + startPadding;
|
|
36
|
-
const
|
|
37
|
-
if (
|
|
38
|
-
reportedIndex.current =
|
|
39
|
-
onChange(createEvent("change", { index:
|
|
38
|
+
const firstShownIndex = [...element.children].findIndex((item) => item.offsetLeft + item.offsetWidth / 2 >= visibleStart);
|
|
39
|
+
if (firstShownIndex !== -1 && firstShownIndex !== reportedIndex.current) {
|
|
40
|
+
reportedIndex.current = firstShownIndex;
|
|
41
|
+
onChange(createEvent("change", { index: firstShownIndex }));
|
|
40
42
|
}
|
|
41
43
|
}, REST_DELAY_MS);
|
|
42
44
|
} : void 0,
|
package/dist/components/sheet.js
CHANGED
|
@@ -16,7 +16,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
16
16
|
const SheetPanel = ({ open, title, showCloseIcon = false, onClose, children, ...padding }) => {
|
|
17
17
|
const { colors, radius } = useTheme();
|
|
18
18
|
const container = usePortalContainer();
|
|
19
|
-
const
|
|
19
|
+
const cornerRadius = radius * CARD_RADIUS_SCALE;
|
|
20
20
|
return /* @__PURE__ */ jsx(DialogRoot, {
|
|
21
21
|
open,
|
|
22
22
|
onOpenChange: (next) => {
|
|
@@ -51,8 +51,8 @@ const SheetPanel = ({ open, title, showCloseIcon = false, onClose, children, ...
|
|
|
51
51
|
end: 16,
|
|
52
52
|
bottom: 24
|
|
53
53
|
}),
|
|
54
|
-
borderTopLeftRadius:
|
|
55
|
-
borderTopRightRadius:
|
|
54
|
+
borderTopLeftRadius: cornerRadius,
|
|
55
|
+
borderTopRightRadius: cornerRadius,
|
|
56
56
|
background: colors.surface,
|
|
57
57
|
color: colors.text,
|
|
58
58
|
fontFamily: FONT_FAMILY,
|