@monimesl/dot-renderer-react 0.1.0-alpha.19 → 0.1.0-alpha.21

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/dist/color.js CHANGED
@@ -1,7 +1,10 @@
1
1
  //#region src/color.ts
2
2
  const READABLE_CONTRAST = 4.5;
3
3
  function contrast(first, second) {
4
- const [lighter, darker] = [luminance(first), luminance(second)].sort((a, b) => b - a);
4
+ const firstLuminance = luminance(first);
5
+ const secondLuminance = luminance(second);
6
+ const lighter = Math.max(firstLuminance, secondLuminance);
7
+ const darker = Math.min(firstLuminance, secondLuminance);
5
8
  return (lighter + .05) / (darker + .05);
6
9
  }
7
10
  function darken(color, points) {
@@ -9,12 +12,14 @@ function darken(color, points) {
9
12
  return toHex(fromHsl(hue, saturation, Math.max(0, lightness - points / 100)));
10
13
  }
11
14
  function luminance(color) {
12
- const [red, green, blue] = channels(color).map((channel) => {
13
- const share = channel / 255;
14
- return share <= .03928 ? share / 12.92 : ((share + .055) / 1.055) ** 2.4;
15
- });
15
+ const [red, green, blue] = channels(color).map(linearLight);
16
16
  return .2126 * red + .7152 * green + .0722 * blue;
17
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
+ }
18
23
  function channels(color) {
19
24
  let hex = color.slice(1);
20
25
  if (hex.length === 3 || hex.length === 4) hex = [...hex].map((digit) => digit + digit).join("");
@@ -33,13 +38,11 @@ function toHex(rgb) {
33
38
  return `#${rgb.map((channel) => Math.round(channel).toString(16).padStart(2, "0")).join("")}`;
34
39
  }
35
40
  function toHsl([red, green, blue]) {
36
- const [r, g, b] = [
37
- red / 255,
38
- green / 255,
39
- blue / 255
40
- ];
41
- const max = Math.max(r, g, b);
42
- const min = Math.min(r, g, b);
41
+ const redShare = red / 255;
42
+ const greenShare = green / 255;
43
+ const blueShare = blue / 255;
44
+ const max = Math.max(redShare, greenShare, blueShare);
45
+ const min = Math.min(redShare, greenShare, blueShare);
43
46
  const lightness = (max + min) / 2;
44
47
  const chroma = max - min;
45
48
  if (chroma === 0) return [
@@ -49,9 +52,9 @@ function toHsl([red, green, blue]) {
49
52
  ];
50
53
  const saturation = chroma / (1 - Math.abs(2 * lightness - 1));
51
54
  let hue;
52
- if (max === r) hue = (g - b) / chroma % 6;
53
- else if (max === g) hue = (b - r) / chroma + 2;
54
- else hue = (r - g) / chroma + 4;
55
+ if (max === redShare) hue = (greenShare - blueShare) / chroma % 6;
56
+ else if (max === greenShare) hue = (blueShare - redShare) / chroma + 2;
57
+ else hue = (redShare - greenShare) / chroma + 4;
55
58
  return [
56
59
  (hue * 60 + 360) % 360,
57
60
  saturation,
@@ -60,45 +63,44 @@ function toHsl([red, green, blue]) {
60
63
  }
61
64
  function fromHsl(hue, saturation, lightness) {
62
65
  const chroma = (1 - Math.abs(2 * lightness - 1)) * saturation;
63
- const second = chroma * (1 - Math.abs(hue / 60 % 2 - 1));
64
- const sector = Math.floor(hue / 60) % 6;
65
- const [r, g, b] = [
66
+ const middle = chroma * (1 - Math.abs(hue / 60 % 2 - 1));
67
+ const [red, green, blue] = [
66
68
  [
67
69
  chroma,
68
- second,
70
+ middle,
69
71
  0
70
72
  ],
71
73
  [
72
- second,
74
+ middle,
73
75
  chroma,
74
76
  0
75
77
  ],
76
78
  [
77
79
  0,
78
80
  chroma,
79
- second
81
+ middle
80
82
  ],
81
83
  [
82
84
  0,
83
- second,
85
+ middle,
84
86
  chroma
85
87
  ],
86
88
  [
87
- second,
89
+ middle,
88
90
  0,
89
91
  chroma
90
92
  ],
91
93
  [
92
94
  chroma,
93
95
  0,
94
- second
96
+ middle
95
97
  ]
96
- ][sector];
98
+ ][Math.floor(hue / 60) % 6];
97
99
  const lift = lightness - chroma / 2;
98
100
  return [
99
- (r + lift) * 255,
100
- (g + lift) * 255,
101
- (b + lift) * 255
101
+ (red + lift) * 255,
102
+ (green + lift) * 255,
103
+ (blue + lift) * 255
102
104
  ];
103
105
  }
104
106
  //#endregion
@@ -10,9 +10,9 @@ const AMOUNT_FONT_SIZE = 28;
10
10
  const DEFAULT_CURRENCY = "SLE";
11
11
  const AmountInput$1 = ({ value, currency = DEFAULT_CURRENCY, minorUnits, unit = "minor", label, placeholder, hint, error, disabled, onChange }) => {
12
12
  const { colors } = useTheme();
13
- const places = minorUnits === void 0 ? currencyMinorUnits(currency) : Math.max(0, Math.round(minorUnits));
14
- const scale = unit === "major" ? 10 ** places : 1;
15
- const show = (minor) => formatMinorUnits(minor, places);
13
+ const decimalPlaces = minorUnits === void 0 ? currencyMinorUnits(currency) : Math.max(0, Math.round(minorUnits));
14
+ const scale = unit === "major" ? 10 ** decimalPlaces : 1;
15
+ const show = (minor) => formatMinorUnits(minor, decimalPlaces);
16
16
  const [text, typeText, reshowText] = useTypedText(amountText(value, scale), onChange !== void 0, (sent) => sent === "" ? "" : show(Number(sent)));
17
17
  const box = useFieldBox(error, disabled);
18
18
  const { noteId, controlAttributes } = useFieldNote(hint, error);
@@ -40,18 +40,18 @@ const AmountInput$1 = ({ value, currency = DEFAULT_CURRENCY, minorUnits, unit =
40
40
  }) : null, /* @__PURE__ */ jsx("input", {
41
41
  value: text,
42
42
  placeholder: placeholder ?? show(0),
43
- inputMode: places > 0 ? "decimal" : "numeric",
43
+ inputMode: decimalPlaces > 0 ? "decimal" : "numeric",
44
44
  disabled,
45
45
  ...controlAttributes,
46
46
  onFocus: box.onFocus,
47
47
  onBlur: () => {
48
48
  box.onBlur();
49
- const amount = toMinorUnits(text, places);
49
+ const amount = toMinorUnits(text, decimalPlaces);
50
50
  if (amount !== null) reshowText(show(amount));
51
51
  },
52
52
  onChange: (event) => {
53
- const typed = cleanAmount(event.currentTarget.value, places);
54
- const amount = toMinorUnits(typed, places);
53
+ const typed = cleanAmount(event.currentTarget.value, decimalPlaces);
54
+ const amount = toMinorUnits(typed, decimalPlaces);
55
55
  typeText(typed, amount === null ? "" : String(amount));
56
56
  onChange?.(createEvent("change", { value: amount === null ? null : amount / scale }));
57
57
  },
@@ -79,23 +79,26 @@ function amountText(value, scale) {
79
79
  if (value === void 0) return;
80
80
  return Number.isFinite(value) ? String(Math.round(value * scale)) : "";
81
81
  }
82
- function cleanAmount(typed, places) {
82
+ function cleanAmount(typed, decimalPlaces) {
83
83
  const [whole = "", ...fractions] = typed.replace(/[^\d.]/g, "").split(".");
84
84
  const digits = whole.replace(/^0+/, "") || whole.slice(0, 1);
85
- if (places === 0 || fractions.length === 0) return groupThousands(digits);
86
- const fraction = fractions.join("").slice(0, places);
85
+ if (decimalPlaces === 0 || fractions.length === 0) return groupThousands(digits);
86
+ const fraction = fractions.join("").slice(0, decimalPlaces);
87
87
  return `${groupThousands(digits) || "0"}.${fraction}`;
88
88
  }
89
- function toMinorUnits(text, places) {
89
+ function toMinorUnits(text, decimalPlaces) {
90
90
  const plain = text.replaceAll(",", "");
91
91
  if (plain === "") return null;
92
92
  const [whole = "", fraction = ""] = plain.split(".");
93
- return Number(`${whole}${fraction.padEnd(places, "0").slice(0, places)}`);
93
+ const fractionDigits = fraction.padEnd(decimalPlaces, "0").slice(0, decimalPlaces);
94
+ return Number(`${whole}${fractionDigits}`);
94
95
  }
95
- function formatMinorUnits(minorUnits, places) {
96
- const digits = String(Math.abs(minorUnits)).padStart(places + 1, "0");
97
- const grouped = groupThousands(digits.slice(0, digits.length - places));
98
- return places === 0 ? grouped : `${grouped}.${digits.slice(digits.length - places)}`;
96
+ function formatMinorUnits(minorUnits, decimalPlaces) {
97
+ const digits = String(Math.abs(minorUnits)).padStart(decimalPlaces + 1, "0");
98
+ const wholeEnd = digits.length - decimalPlaces;
99
+ const grouped = groupThousands(digits.slice(0, wholeEnd));
100
+ if (decimalPlaces === 0) return grouped;
101
+ return `${grouped}.${digits.slice(wholeEnd)}`;
99
102
  }
100
103
  function groupThousands(digits) {
101
104
  const groups = [];
@@ -0,0 +1,6 @@
1
+ import { ReactComponent } from "../types.js";
2
+ import { Avatar } from "@monimesl/dot-core";
3
+ //#region src/components/avatar.d.ts
4
+ declare const Avatar$1: ReactComponent<typeof Avatar>;
5
+ //#endregion
6
+ export { Avatar$1 as Avatar };
@@ -0,0 +1,63 @@
1
+ import { useTheme } from "../theme.js";
2
+ import { WEIGHTS } from "./tokens.js";
3
+ import { USER_ARTWORK } from "./icon-artwork.js";
4
+ import { IconSvg } from "./icon-svg.js";
5
+ import { useState } from "react";
6
+ import { jsx } from "react/jsx-runtime";
7
+ //#region src/components/avatar.tsx
8
+ const AVATAR_SIZE = {
9
+ small: 32,
10
+ medium: 40,
11
+ large: 56
12
+ };
13
+ function initials(name) {
14
+ const words = name.trim().split(/\s+/).filter(Boolean);
15
+ if (words.length === 0) return "";
16
+ return (words.length === 1 ? [words[0]] : [words[0], words[words.length - 1]]).map((word) => word.charAt(0).toUpperCase()).join("");
17
+ }
18
+ const Avatar = ({ name = "", image, size = "medium" }) => {
19
+ const { colors } = useTheme();
20
+ const [failed, setFailed] = useState();
21
+ const pixels = AVATAR_SIZE[size];
22
+ const letters = initials(name);
23
+ let content;
24
+ if (image && failed !== image) content = /* @__PURE__ */ jsx("img", {
25
+ src: image,
26
+ alt: "",
27
+ onError: () => setFailed(image),
28
+ style: {
29
+ width: "100%",
30
+ height: "100%",
31
+ objectFit: "cover"
32
+ }
33
+ });
34
+ else if (letters) content = letters;
35
+ else content = /* @__PURE__ */ jsx(IconSvg, {
36
+ artwork: USER_ARTWORK,
37
+ size: Math.round(pixels * .55),
38
+ color: "currentColor"
39
+ });
40
+ return /* @__PURE__ */ jsx("span", {
41
+ className: "dot-avatar",
42
+ role: "img",
43
+ "aria-label": name || void 0,
44
+ style: {
45
+ display: "inline-flex",
46
+ flexShrink: 0,
47
+ alignItems: "center",
48
+ justifyContent: "center",
49
+ width: pixels,
50
+ height: pixels,
51
+ borderRadius: "50%",
52
+ overflow: "hidden",
53
+ background: colors.muted,
54
+ color: colors.subtle,
55
+ fontSize: Math.round(pixels * .4),
56
+ fontWeight: WEIGHTS.bold,
57
+ lineHeight: 1
58
+ },
59
+ children: content
60
+ });
61
+ };
62
+ //#endregion
63
+ export { Avatar };
@@ -1,6 +1,6 @@
1
1
  import { CARD_RADIUS_SCALE } from "./tokens.js";
2
- import { toneBackground } from "./tones.js";
3
- import { BACKGROUNDS, TONES } from "@monimesl/dot-core";
2
+ import { isTone, toneBackground } from "./tones.js";
3
+ import { BACKGROUNDS } from "@monimesl/dot-core";
4
4
  //#region src/components/box.ts
5
5
  const RADIUS_SCALE = {
6
6
  none: 0,
@@ -10,7 +10,6 @@ const RADIUS_SCALE = {
10
10
  };
11
11
  const FULL_RADIUS = 9999;
12
12
  const BACKGROUND_WORDS = new Set(BACKGROUNDS.words);
13
- const TONE_WORDS = new Set(TONES);
14
13
  function boxStyle(props, theme, look = {}) {
15
14
  const background = props.background ?? look.background;
16
15
  const border = props.border ?? look.border;
@@ -39,7 +38,7 @@ function boxStyle(props, theme, look = {}) {
39
38
  return style;
40
39
  }
41
40
  function backgroundColor(background, theme) {
42
- if (TONE_WORDS.has(background)) return toneBackground(theme.colors, background);
41
+ if (isTone(background)) return toneBackground(theme.colors, background);
43
42
  if (BACKGROUND_WORDS.has(background)) return theme.colors[background];
44
43
  return customColor(background, theme);
45
44
  }
@@ -1,6 +1,7 @@
1
1
  import { useTheme } from "../theme.js";
2
2
  import { SPACE } from "./tokens.js";
3
3
  import { paddingStyle } from "./padding.js";
4
+ import { clamp } from "./utils.js";
4
5
  import { createEvent } from "@monimesl/dot-core";
5
6
  import { Children, Fragment, isValidElement, useEffect, useEffectEvent, useRef, useState } from "react";
6
7
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -45,7 +46,8 @@ const Carousel$1 = ({ autoplay = false, interval = 4e3, loop = false, indicator
45
46
  };
46
47
  const step = (direction) => {
47
48
  const beyondEnd = current + direction < 0 || current + direction >= count;
48
- moveTo(!looping && beyondEnd ? shown : shown + direction);
49
+ if (!looping && beyondEnd) moveTo(shown);
50
+ else moveTo(shown + direction);
49
51
  };
50
52
  const advance = useEffectEvent(() => {
51
53
  if (!looping && current === count - 1) moveTo(first);
@@ -75,8 +77,8 @@ const Carousel$1 = ({ autoplay = false, interval = 4e3, loop = false, indicator
75
77
  count
76
78
  ]);
77
79
  const gestureOf = (event) => {
78
- const touch = gesture.current;
79
- return touch?.pointerId === event.pointerId ? touch : null;
80
+ const inProgress = gesture.current;
81
+ return inProgress?.pointerId === event.pointerId ? inProgress : null;
80
82
  };
81
83
  const endGesture = () => {
82
84
  gesture.current = null;
@@ -98,32 +100,33 @@ const Carousel$1 = ({ autoplay = false, interval = 4e3, loop = false, indicator
98
100
  setWidth(viewport.current?.clientWidth ?? 0);
99
101
  };
100
102
  const onPointerMove = (event) => {
101
- const touch = gestureOf(event);
102
- if (!touch) return;
103
- const dx = event.clientX - touch.startX;
104
- const dy = event.clientY - touch.startY;
105
- if (!touch.swiping) {
106
- if (Math.abs(dx) < TAP_SLOP && Math.abs(dy) < TAP_SLOP) return;
107
- if (Math.abs(dy) > Math.abs(dx)) {
103
+ const swipe = gestureOf(event);
104
+ if (!swipe) return;
105
+ const movedX = event.clientX - swipe.startX;
106
+ const movedY = event.clientY - swipe.startY;
107
+ if (!swipe.swiping) {
108
+ if (Math.abs(movedX) < TAP_SLOP && Math.abs(movedY) < TAP_SLOP) return;
109
+ if (Math.abs(movedY) > Math.abs(movedX)) {
108
110
  endGesture();
109
111
  return;
110
112
  }
111
- touch.swiping = true;
113
+ swipe.swiping = true;
112
114
  swiped.current = true;
113
115
  event.currentTarget.setPointerCapture?.(event.pointerId);
114
116
  setAnimated(false);
115
117
  }
116
- const pastEnd = !looping && (current === 0 && dx > 0 || current === count - 1 && dx < 0);
117
- setDrag(pastEnd ? dx * EDGE_RESISTANCE : dx);
118
+ const beforeFirst = current === 0 && movedX > 0;
119
+ const afterLast = current === count - 1 && movedX < 0;
120
+ setDrag(!looping && (beforeFirst || afterLast) ? movedX * EDGE_RESISTANCE : movedX);
118
121
  };
119
122
  const onPointerUp = (event) => {
120
- const touch = gestureOf(event);
121
- if (!touch) return;
123
+ const swipe = gestureOf(event);
124
+ if (!swipe) return;
122
125
  endGesture();
123
- if (!touch.swiping) return;
124
- const dx = event.clientX - touch.startX;
125
- const speed = Math.abs(dx) / Math.max(1, event.timeStamp - touch.startTime);
126
- if (Math.abs(dx) > width * SWIPE_DISTANCE || speed > SWIPE_SPEED) step(dx < 0 ? 1 : -1);
126
+ if (!swipe.swiping) return;
127
+ const movedX = event.clientX - swipe.startX;
128
+ const speed = Math.abs(movedX) / Math.max(1, event.timeStamp - swipe.startTime);
129
+ if (Math.abs(movedX) > width * SWIPE_DISTANCE || speed > SWIPE_SPEED) step(movedX < 0 ? 1 : -1);
127
130
  else moveTo(shown);
128
131
  };
129
132
  const gapWidth = SPACE[gap];
@@ -241,9 +244,6 @@ function slidesOf(children, keyPrefix = "") {
241
244
  }
242
245
  return slides;
243
246
  }
244
- function clamp(value, min, max) {
245
- return Math.max(min, Math.min(value, max));
246
- }
247
247
  function slideIndex(index, count) {
248
248
  return clamp(Math.round(index), 0, count - 1);
249
249
  }
@@ -0,0 +1,6 @@
1
+ import { ReactComponent } from "../types.js";
2
+ import { Disclosure } from "@monimesl/dot-core";
3
+ //#region src/components/disclosure.d.ts
4
+ declare const Disclosure$1: ReactComponent<typeof Disclosure>;
5
+ //#endregion
6
+ export { Disclosure$1 as Disclosure };
@@ -0,0 +1,76 @@
1
+ import { useTheme } from "../theme.js";
2
+ import { FONT_SIZE, ICON_SIZE, SPACE, WEIGHTS } from "./tokens.js";
3
+ import { CHEVRON_DOWN_ARTWORK } from "./icon-artwork.js";
4
+ import { IconSvg } from "./icon-svg.js";
5
+ import { createEvent } from "@monimesl/dot-core";
6
+ import { useState } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ //#region src/components/disclosure.tsx
9
+ const Disclosure$1 = ({ title, subtitle, open: startsOpen = false, children, onToggle }) => {
10
+ const { colors } = useTheme();
11
+ const [open, setOpen] = useState(startsOpen);
12
+ return /* @__PURE__ */ jsxs("details", {
13
+ className: "dot-disclosure",
14
+ open,
15
+ onToggle: (event) => {
16
+ const next = event.currentTarget.open;
17
+ if (next !== open) {
18
+ setOpen(next);
19
+ onToggle?.(createEvent("toggle", { open: next }));
20
+ }
21
+ },
22
+ style: { color: colors.text },
23
+ children: [/* @__PURE__ */ jsxs("summary", {
24
+ style: {
25
+ display: "flex",
26
+ alignItems: "center",
27
+ gap: SPACE.medium,
28
+ padding: "12px 0",
29
+ cursor: "pointer"
30
+ },
31
+ children: [/* @__PURE__ */ jsxs("span", {
32
+ style: {
33
+ display: "flex",
34
+ flexDirection: "column",
35
+ gap: 2,
36
+ flex: 1,
37
+ minWidth: 0
38
+ },
39
+ children: [/* @__PURE__ */ jsx("span", {
40
+ style: {
41
+ fontSize: FONT_SIZE.body,
42
+ fontWeight: WEIGHTS.medium
43
+ },
44
+ children: title
45
+ }), subtitle ? /* @__PURE__ */ jsx("span", {
46
+ style: {
47
+ fontSize: FONT_SIZE.caption,
48
+ color: colors.subtle
49
+ },
50
+ children: subtitle
51
+ }) : null]
52
+ }), /* @__PURE__ */ jsx("span", {
53
+ style: {
54
+ display: "flex",
55
+ transform: open ? "rotate(180deg)" : "none",
56
+ transition: "transform 0.2s"
57
+ },
58
+ children: /* @__PURE__ */ jsx(IconSvg, {
59
+ artwork: CHEVRON_DOWN_ARTWORK,
60
+ size: ICON_SIZE.medium,
61
+ color: colors.subtle
62
+ })
63
+ })]
64
+ }), /* @__PURE__ */ jsx("div", {
65
+ style: {
66
+ display: "flex",
67
+ flexDirection: "column",
68
+ gap: SPACE.medium,
69
+ paddingBottom: 12
70
+ },
71
+ children
72
+ })]
73
+ });
74
+ };
75
+ //#endregion
76
+ export { Disclosure$1 as Disclosure };
@@ -1,13 +1,17 @@
1
1
  import { useTheme } from "../theme.js";
2
2
  import { FONT_SIZE, ICON_SIZE, SPACE, WEIGHTS } from "./tokens.js";
3
+ import { CLOSE_ARTWORK } from "./icon-artwork.js";
4
+ import { IconSvg } from "./icon-svg.js";
3
5
  import { insets, paddingStyle } from "./padding.js";
4
- import { STATUS_ICONS, toneBackground, toneColor } from "./tones.js";
5
- import { IconGraphic } from "./icon.js";
6
+ import { clamp } from "./utils.js";
7
+ import { STATUS_ARTWORK, toneBackground, toneColor } from "./tones.js";
8
+ import { IconButton } from "./icon-button.js";
9
+ import { createEvent } from "@monimesl/dot-core";
6
10
  import { jsx, jsxs } from "react/jsx-runtime";
7
11
  //#region src/components/feedback.tsx
8
- const ProgressBar = ({ value = 0 }) => {
12
+ const ProgressBar$1 = ({ value = 0 }) => {
9
13
  const { colors } = useTheme();
10
- const percent = Math.min(100, Math.max(0, value));
14
+ const percent = clamp(value, 0, 100);
11
15
  return /* @__PURE__ */ jsx("div", {
12
16
  className: "dot-progress-bar",
13
17
  role: "progressbar",
@@ -29,7 +33,7 @@ const ProgressBar = ({ value = 0 }) => {
29
33
  } })
30
34
  });
31
35
  };
32
- const Notice = ({ tone = "default", title, children, ...padding }) => {
36
+ const Notice$1 = ({ tone = "default", title, children, onClose, ...padding }) => {
33
37
  const { colors, radius } = useTheme();
34
38
  return /* @__PURE__ */ jsxs("div", {
35
39
  className: "dot-notice",
@@ -44,25 +48,37 @@ const Notice = ({ tone = "default", title, children, ...padding }) => {
44
48
  fontSize: FONT_SIZE.body,
45
49
  lineHeight: "normal"
46
50
  },
47
- children: [/* @__PURE__ */ jsx(IconGraphic, {
48
- name: STATUS_ICONS[tone],
49
- size: ICON_SIZE.medium,
50
- color: toneColor(colors, tone)
51
- }), /* @__PURE__ */ jsxs("div", {
52
- style: {
53
- display: "flex",
54
- flexDirection: "column",
55
- gap: 2,
56
- minWidth: 0
57
- },
58
- children: [title ? /* @__PURE__ */ jsx("span", {
59
- style: { fontWeight: WEIGHTS.bold },
60
- children: title
61
- }) : null, children ? /* @__PURE__ */ jsx("span", { children }) : null]
62
- })]
51
+ children: [
52
+ /* @__PURE__ */ jsx(IconSvg, {
53
+ artwork: STATUS_ARTWORK[tone],
54
+ size: ICON_SIZE.medium,
55
+ color: toneColor(colors, tone)
56
+ }),
57
+ /* @__PURE__ */ jsxs("div", {
58
+ style: {
59
+ display: "flex",
60
+ flexDirection: "column",
61
+ gap: 2,
62
+ minWidth: 0
63
+ },
64
+ children: [title ? /* @__PURE__ */ jsx("span", {
65
+ style: { fontWeight: WEIGHTS.bold },
66
+ children: title
67
+ }) : null, children ? /* @__PURE__ */ jsx("span", { children }) : null]
68
+ }),
69
+ onClose ? /* @__PURE__ */ jsx(IconButton, {
70
+ artwork: CLOSE_ARTWORK,
71
+ label: "Close",
72
+ onPress: () => onClose(createEvent("close")),
73
+ style: {
74
+ marginLeft: "auto",
75
+ alignSelf: "flex-start"
76
+ }
77
+ }) : null
78
+ ]
63
79
  });
64
80
  };
65
- const Badge = ({ tone = "default", children }) => {
81
+ const Badge$1 = ({ tone = "default", children }) => {
66
82
  const { colors } = useTheme();
67
83
  return /* @__PURE__ */ jsx("span", {
68
84
  className: "dot-badge",
@@ -82,4 +98,4 @@ const Badge = ({ tone = "default", children }) => {
82
98
  });
83
99
  };
84
100
  //#endregion
85
- export { Badge, Notice, ProgressBar };
101
+ export { Badge$1 as Badge, Notice$1 as Notice, ProgressBar$1 as ProgressBar };