@patternmode/status 0.1.0 → 0.2.1
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/index.mjs +22 -23
- package/dist/index.mjs.map +1 -1
- package/dist/status-mark-types.d.ts.map +1 -1
- package/dist/status-mark.d.ts +1 -1
- package/dist/status-mark.d.ts.map +1 -1
- package/package.json +24 -24
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { easings } from "@howells/motion";
|
|
1
2
|
import { getSizeVariableStyle, joinClassNames } from "@patternmode/system";
|
|
2
3
|
import { useEffect, useReducer, useRef } from "react";
|
|
3
4
|
import { LazyMotion, domMax, m, useReducedMotion } from "motion/react";
|
|
@@ -46,7 +47,13 @@ const PROGRESS_STEP = {
|
|
|
46
47
|
};
|
|
47
48
|
const snapProgress = (value) => {
|
|
48
49
|
if (value === void 0 || Number.isNaN(value)) return 0;
|
|
49
|
-
|
|
50
|
+
switch (Math.round(Math.min(100, Math.max(0, value)) / 25) * 25) {
|
|
51
|
+
case 25: return 25;
|
|
52
|
+
case 50: return 50;
|
|
53
|
+
case 75: return 75;
|
|
54
|
+
case 100: return 100;
|
|
55
|
+
default: return 0;
|
|
56
|
+
}
|
|
50
57
|
};
|
|
51
58
|
/** Resolves named or numeric progress input into a discrete StatusMark step. */
|
|
52
59
|
const resolveStatusProgress = ({ status, value }) => {
|
|
@@ -54,7 +61,7 @@ const resolveStatusProgress = ({ status, value }) => {
|
|
|
54
61
|
progress: null,
|
|
55
62
|
status
|
|
56
63
|
};
|
|
57
|
-
if (status) return {
|
|
64
|
+
if (status !== void 0) return {
|
|
58
65
|
progress: STEP_PROGRESS[status],
|
|
59
66
|
status
|
|
60
67
|
};
|
|
@@ -77,21 +84,11 @@ const getTransition = (motion, reducedMotion) => {
|
|
|
77
84
|
if (motion === false || motion === "reduced" || reducedMotion) return { duration: .01 };
|
|
78
85
|
if (motion === "snap") return {
|
|
79
86
|
duration: .16,
|
|
80
|
-
ease:
|
|
81
|
-
.22,
|
|
82
|
-
1,
|
|
83
|
-
.36,
|
|
84
|
-
1
|
|
85
|
-
]
|
|
87
|
+
ease: easings.snappy
|
|
86
88
|
};
|
|
87
89
|
return {
|
|
88
90
|
duration: .28,
|
|
89
|
-
ease:
|
|
90
|
-
.4,
|
|
91
|
-
0,
|
|
92
|
-
.2,
|
|
93
|
-
1
|
|
94
|
-
]
|
|
91
|
+
ease: easings.smooth
|
|
95
92
|
};
|
|
96
93
|
};
|
|
97
94
|
const getFillMotionDuration = (motion, reducedMotion) => {
|
|
@@ -129,8 +126,8 @@ const getRootStyle = ({ color, size = "base", style, trackColor }) => {
|
|
|
129
126
|
...getSizeVariableStyle(size, "--patternmode-status-size"),
|
|
130
127
|
...style
|
|
131
128
|
};
|
|
132
|
-
if (color) rootStyle["--patternmode-status-color"] = color;
|
|
133
|
-
if (trackColor) rootStyle["--patternmode-status-track"] = trackColor;
|
|
129
|
+
if (color !== void 0 && color !== "") rootStyle["--patternmode-status-color"] = color;
|
|
130
|
+
if (trackColor !== void 0 && trackColor !== "") rootStyle["--patternmode-status-track"] = trackColor;
|
|
134
131
|
return rootStyle;
|
|
135
132
|
};
|
|
136
133
|
const StatusFillSweep = ({ hasReducedMotion, motion, progress, radius }) => {
|
|
@@ -138,14 +135,17 @@ const StatusFillSweep = ({ hasReducedMotion, motion, progress, radius }) => {
|
|
|
138
135
|
const renderedProgressRef = useRef(progress);
|
|
139
136
|
const [renderedProgress, setRenderedProgress] = useReducer(setProgress, progress);
|
|
140
137
|
useEffect(() => {
|
|
138
|
+
const cancelFillAnimation = () => {
|
|
139
|
+
if (animationFrameRef.current !== null) cancelAnimationFrame(animationFrameRef.current);
|
|
140
|
+
};
|
|
141
141
|
const duration = getFillMotionDuration(motion, hasReducedMotion);
|
|
142
142
|
const startProgress = renderedProgressRef.current;
|
|
143
143
|
const progressDelta = progress - startProgress;
|
|
144
|
-
|
|
144
|
+
cancelFillAnimation();
|
|
145
145
|
if (duration === 0 || progressDelta === 0) {
|
|
146
146
|
renderedProgressRef.current = progress;
|
|
147
147
|
setRenderedProgress(progress);
|
|
148
|
-
return;
|
|
148
|
+
return cancelFillAnimation;
|
|
149
149
|
}
|
|
150
150
|
const startTime = performance.now();
|
|
151
151
|
const tick = (now) => {
|
|
@@ -161,9 +161,7 @@ const StatusFillSweep = ({ hasReducedMotion, motion, progress, radius }) => {
|
|
|
161
161
|
animationFrameRef.current = null;
|
|
162
162
|
};
|
|
163
163
|
animationFrameRef.current = requestAnimationFrame(tick);
|
|
164
|
-
return
|
|
165
|
-
if (animationFrameRef.current !== null) cancelAnimationFrame(animationFrameRef.current);
|
|
166
|
-
};
|
|
164
|
+
return cancelFillAnimation;
|
|
167
165
|
}, [
|
|
168
166
|
hasReducedMotion,
|
|
169
167
|
motion,
|
|
@@ -239,9 +237,10 @@ const StatusMark = ({ className, color, label, motion = "smooth", size = "base",
|
|
|
239
237
|
style,
|
|
240
238
|
trackColor
|
|
241
239
|
});
|
|
240
|
+
const hasLabel = label !== void 0 && label !== "";
|
|
242
241
|
return /* @__PURE__ */ jsx("span", {
|
|
243
242
|
...props,
|
|
244
|
-
"aria-hidden":
|
|
243
|
+
"aria-hidden": hasLabel ? void 0 : true,
|
|
245
244
|
"aria-label": label,
|
|
246
245
|
className: joinClassNames("patternmode-status-mark", className),
|
|
247
246
|
"data-motion": motion === false ? "false" : motion,
|
|
@@ -250,7 +249,7 @@ const StatusMark = ({ className, color, label, motion = "smooth", size = "base",
|
|
|
250
249
|
"data-status": state.status,
|
|
251
250
|
"data-tone": tone,
|
|
252
251
|
"data-variant": variant,
|
|
253
|
-
role:
|
|
252
|
+
role: hasLabel ? "img" : void 0,
|
|
254
253
|
style: rootStyle,
|
|
255
254
|
children: /* @__PURE__ */ jsx(LazyMotion, {
|
|
256
255
|
features: domMax,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/status-mark-types.ts","../src/status-mark.tsx"],"sourcesContent":["import type { HTMLAttributes } from \"react\";\n\nexport const STATUS_MARK_PROGRESS_STEPS = [\n \"null\",\n \"empty\",\n \"quarter\",\n \"half\",\n \"three-quarter\",\n \"full\",\n] as const;\n\nexport const STATUS_MARK_STATUSES = STATUS_MARK_PROGRESS_STEPS;\nexport const STATUS_MARK_PROGRESS_VALUES = [0, 25, 50, 75, 100] as const;\nexport const STATUS_MARK_TONES = [\"neutral\", \"accent\", \"muted\"] as const;\nexport const STATUS_MARK_VARIANTS = [\"fill\", \"border\"] as const;\nexport const STATUS_MARK_MOTIONS = [\"smooth\", \"snap\", \"reduced\"] as const;\n\nexport type StatusMarkMotion = (typeof STATUS_MARK_MOTIONS)[number] | false;\nexport type StatusMarkProgressStep = (typeof STATUS_MARK_PROGRESS_STEPS)[number];\nexport type StatusMarkProgressValue = (typeof STATUS_MARK_PROGRESS_VALUES)[number];\nexport type StatusMarkStatus = StatusMarkProgressStep;\nexport type StatusMarkTone = (typeof STATUS_MARK_TONES)[number];\nexport type StatusMarkVariant = (typeof STATUS_MARK_VARIANTS)[number];\n\nexport type ResolvedStatusProgress =\n | {\n progress: null;\n status: \"null\";\n }\n | {\n progress: StatusMarkProgressValue;\n status: Exclude<StatusMarkProgressStep, \"null\">;\n };\n\nexport interface StatusMarkProps extends Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /**\n * Active progress color. Overrides the selected visual `tone` when supplied.\n */\n color?: string;\n /**\n * Accessible label for the visual state. Omit only when adjacent text already\n * names the same progress and the mark should be decorative.\n */\n label?: string;\n /**\n * Transition preset for movement between progress steps.\n *\n * Default `\"smooth\"`.\n */\n motion?: StatusMarkMotion;\n /**\n * Named discrete progress step. Use `\"null\"` only when progress is explicitly\n * not yet known or measured.\n */\n status?: StatusMarkProgressStep;\n /**\n * Size token used for the mark dimensions.\n *\n * Default `\"base\"`.\n */\n size?: \"2xl\" | \"2xs\" | \"3xl\" | \"base\" | \"lg\" | \"sm\" | \"xl\" | \"xs\";\n /**\n * Visual emphasis treatment. Tone changes color only; progress shape carries\n * meaning.\n *\n * Default `\"neutral\"`.\n */\n tone?: StatusMarkTone;\n /**\n * Color used for inactive track or placeholder structure.\n */\n trackColor?: string;\n /**\n * Numeric progress input. Values are clamped from 0 to 100 and snapped to the\n * nearest discrete visual step: 0, 25, 50, 75, or 100.\n */\n value?: number;\n /**\n * Visual treatment for known progress. Null progress renders the same dashed\n * placeholder in every variant.\n *\n * Default `\"fill\"`.\n */\n variant?: StatusMarkVariant;\n}\n\nconst STEP_PROGRESS: Record<Exclude<StatusMarkProgressStep, \"null\">, StatusMarkProgressValue> = {\n empty: 0,\n full: 100,\n half: 50,\n quarter: 25,\n \"three-quarter\": 75,\n};\n\nconst PROGRESS_STEP: Record<StatusMarkProgressValue, Exclude<StatusMarkProgressStep, \"null\">> = {\n 0: \"empty\",\n 100: \"full\",\n 25: \"quarter\",\n 50: \"half\",\n 75: \"three-quarter\",\n};\n\nconst snapProgress = (value: number | undefined): StatusMarkProgressValue => {\n if (value === undefined || Number.isNaN(value)) {\n return 0;\n }\n\n const clamped = Math.min(100, Math.max(0, value));\n return (Math.round(clamped / 25) * 25) as StatusMarkProgressValue;\n};\n\n/** Resolves named or numeric progress input into a discrete StatusMark step. */\nexport const resolveStatusProgress = ({\n status,\n value,\n}: Pick<StatusMarkProps, \"status\" | \"value\">): ResolvedStatusProgress => {\n if (status === \"null\") {\n return {\n progress: null,\n status,\n };\n }\n\n if (status) {\n return {\n progress: STEP_PROGRESS[status],\n status,\n };\n }\n\n const progress = snapProgress(value);\n return {\n progress,\n status: PROGRESS_STEP[progress],\n };\n};\n","\"use client\";\n\nimport { getSizeVariableStyle, joinClassNames } from \"@patternmode/system\";\nimport { useEffect, useReducer, useRef } from \"react\";\nimport type { CSSProperties } from \"react\";\nimport { domMax, LazyMotion, m, useReducedMotion } from \"motion/react\";\nimport type { Transition } from \"motion/react\";\n\nimport { resolveStatusProgress } from \"./status-mark-types\";\nimport type {\n ResolvedStatusProgress,\n StatusMarkMotion,\n StatusMarkProgressValue,\n StatusMarkProps,\n} from \"./status-mark-types\";\n\ntype StatusMarkStyle = CSSProperties & Record<`--${string}`, string | number | undefined>;\ninterface MotionPartProps {\n hasReducedMotion: boolean;\n motion: StatusMarkMotion;\n}\n\nconst STATUS_MARK_RADIUS = 8;\nconst STATUS_MARK_STROKE_WIDTH = 1.8;\nconst BORDERLESS_STATUS_MARK_RADIUS = STATUS_MARK_RADIUS + STATUS_MARK_STROKE_WIDTH / 2;\nconst STATUS_MARK_CENTER = 12;\nconst STATUS_MARK_START_ANGLE = -90;\nconst STATUS_MARK_FULL_PROGRESS = 100;\nconst STATUS_SNAP_DURATION_MS = 160;\nconst STATUS_SMOOTH_DURATION_MS = 280;\n\nconst getTransition = (motion: StatusMarkMotion, reducedMotion: boolean): Transition => {\n if (motion === false || motion === \"reduced\" || reducedMotion) {\n return { duration: 0.01 };\n }\n\n if (motion === \"snap\") {\n return { duration: 0.16, ease: [0.22, 1, 0.36, 1] as const };\n }\n\n return { duration: 0.28, ease: [0.4, 0, 0.2, 1] as const };\n};\n\nconst getFillMotionDuration = (motion: StatusMarkMotion, reducedMotion: boolean) => {\n if (motion === false || motion === \"reduced\" || reducedMotion) {\n return 0;\n }\n\n return motion === \"snap\" ? STATUS_SNAP_DURATION_MS : STATUS_SMOOTH_DURATION_MS;\n};\n\nconst easeFillProgress = (progress: number) => {\n if (progress < 0.5) {\n return 4 * progress * progress * progress;\n }\n\n return 1 - (-2 * progress + 2) ** 3 / 2;\n};\n\nconst setProgress = (_current: number, next: number) => next;\n\nconst getFillPath = (progress: number, radius: number) => {\n if (progress <= 0) {\n return `M${STATUS_MARK_CENTER} ${STATUS_MARK_CENTER}`;\n }\n\n if (progress >= 99.9) {\n const diameter = radius * 2;\n\n return [\n `M${STATUS_MARK_CENTER - radius} ${STATUS_MARK_CENTER}`,\n `a${radius} ${radius} 0 1 0 ${diameter} 0`,\n `a${radius} ${radius} 0 1 0 -${diameter} 0`,\n ].join(\" \");\n }\n\n const endAngle = STATUS_MARK_START_ANGLE + (360 * progress) / STATUS_MARK_FULL_PROGRESS;\n const radians = (endAngle * Math.PI) / 180;\n const x = Number((STATUS_MARK_CENTER + radius * Math.cos(radians)).toFixed(3));\n const y = Number((STATUS_MARK_CENTER + radius * Math.sin(radians)).toFixed(3));\n const largeArcFlag = progress > 50 ? 1 : 0;\n\n return [\n `M${STATUS_MARK_CENTER} ${STATUS_MARK_CENTER}`,\n `L${STATUS_MARK_CENTER} ${STATUS_MARK_CENTER - radius}`,\n `A${radius} ${radius} 0 ${largeArcFlag} 1 ${x} ${y}`,\n \"Z\",\n ].join(\" \");\n};\n\nconst getRootStyle = ({\n color,\n size = \"base\",\n style,\n trackColor,\n}: Pick<StatusMarkProps, \"color\" | \"size\" | \"style\" | \"trackColor\">) => {\n const rootStyle: StatusMarkStyle = {\n ...getSizeVariableStyle(size, \"--patternmode-status-size\"),\n ...style,\n };\n\n if (color) {\n rootStyle[\"--patternmode-status-color\"] = color;\n }\n\n if (trackColor) {\n rootStyle[\"--patternmode-status-track\"] = trackColor;\n }\n\n return rootStyle;\n};\n\nconst StatusFillSweep = ({\n hasReducedMotion,\n motion,\n progress,\n radius,\n}: MotionPartProps & { progress: StatusMarkProgressValue; radius: number }) => {\n const animationFrameRef = useRef<number | null>(null);\n const renderedProgressRef = useRef<number>(progress);\n const [renderedProgress, setRenderedProgress] = useReducer(setProgress, progress);\n\n useEffect(() => {\n const duration = getFillMotionDuration(motion, hasReducedMotion);\n const startProgress = renderedProgressRef.current;\n const progressDelta = progress - startProgress;\n\n if (animationFrameRef.current !== null) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n\n if (duration === 0 || progressDelta === 0) {\n renderedProgressRef.current = progress;\n setRenderedProgress(progress);\n return;\n }\n\n const startTime = performance.now();\n\n const tick = (now: number) => {\n const elapsed = Math.min((now - startTime) / duration, 1);\n const nextProgress = startProgress + progressDelta * easeFillProgress(elapsed);\n\n renderedProgressRef.current = nextProgress;\n setRenderedProgress(nextProgress);\n\n if (elapsed < 1) {\n animationFrameRef.current = requestAnimationFrame(tick);\n return;\n }\n\n renderedProgressRef.current = progress;\n animationFrameRef.current = null;\n };\n\n animationFrameRef.current = requestAnimationFrame(tick);\n\n return () => {\n if (animationFrameRef.current !== null) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n };\n }, [hasReducedMotion, motion, progress]);\n\n return (\n <path\n className=\"patternmode-status-mark__fill-sweep\"\n d={getFillPath(renderedProgress, radius)}\n data-testid=\"status-mark-fill-sweep\"\n />\n );\n};\n\nconst StatusArc = ({\n hasReducedMotion,\n motion,\n progress,\n}: MotionPartProps & { progress: StatusMarkProgressValue }) => (\n <m.circle\n animate={{ opacity: progress > 0 ? 1 : 0, pathLength: progress / 100 }}\n className=\"patternmode-status-mark__arc\"\n cx=\"12\"\n cy=\"12\"\n initial={false}\n pathLength=\"1\"\n r=\"8\"\n transition={getTransition(motion, hasReducedMotion)}\n />\n);\n\nconst StatusMarkSvg = ({\n hasReducedMotion,\n motion,\n state,\n variant,\n}: MotionPartProps & {\n state: ResolvedStatusProgress;\n variant: NonNullable<StatusMarkProps[\"variant\"]>;\n}) => (\n <svg aria-hidden=\"true\" className=\"patternmode-status-mark__svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n {state.status === \"null\" ? (\n <circle\n className=\"patternmode-status-mark__track patternmode-status-mark__track--null\"\n cx=\"12\"\n cy=\"12\"\n data-testid=\"status-mark-null\"\n r={STATUS_MARK_RADIUS}\n />\n ) : (\n <>\n {variant === \"fill\" ? (\n <>\n <circle\n className=\"patternmode-status-mark__disc\"\n cx=\"12\"\n cy=\"12\"\n data-testid=\"status-mark-fill\"\n r={BORDERLESS_STATUS_MARK_RADIUS}\n />\n <StatusFillSweep\n hasReducedMotion={hasReducedMotion}\n motion={motion}\n progress={state.progress}\n radius={BORDERLESS_STATUS_MARK_RADIUS}\n />\n </>\n ) : null}\n {variant === \"border\" ? (\n <circle\n className=\"patternmode-status-mark__track\"\n cx=\"12\"\n cy=\"12\"\n data-testid=\"status-mark-border\"\n r={STATUS_MARK_RADIUS}\n />\n ) : null}\n {variant === \"border\" ? (\n <StatusArc\n hasReducedMotion={hasReducedMotion}\n motion={motion}\n progress={state.progress}\n />\n ) : null}\n </>\n )}\n </svg>\n);\n\nexport const StatusMark = ({\n className,\n color,\n label,\n motion = \"smooth\",\n size = \"base\",\n status,\n style,\n tone = \"neutral\",\n trackColor,\n value,\n variant = \"fill\",\n ...props\n}: StatusMarkProps) => {\n const reducedMotion = useReducedMotion();\n const hasReducedMotion = Boolean(reducedMotion);\n const state = resolveStatusProgress({ status, value });\n const rootStyle = getRootStyle({ color, size, style, trackColor });\n\n return (\n <span\n {...props}\n aria-hidden={label ? undefined : true}\n aria-label={label}\n className={joinClassNames(\"patternmode-status-mark\", className)}\n data-motion={motion === false ? \"false\" : motion}\n data-progress={state.progress ?? \"null\"}\n data-slot=\"status-mark\"\n data-status={state.status}\n data-tone={tone}\n data-variant={variant}\n role={label ? \"img\" : undefined}\n style={rootStyle}\n >\n <LazyMotion features={domMax}>\n <StatusMarkSvg\n hasReducedMotion={hasReducedMotion}\n motion={motion}\n state={state}\n variant={variant}\n />\n </LazyMotion>\n </span>\n );\n};\n"],"mappings":";;;;;AAEA,MAAa,6BAA6B;CACxC;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,uBAAuB;AACpC,MAAa,8BAA8B;CAAC;CAAG;CAAI;CAAI;CAAI;AAAG;AAC9D,MAAa,oBAAoB;CAAC;CAAW;CAAU;AAAO;AAC9D,MAAa,uBAAuB,CAAC,QAAQ,QAAQ;AACrD,MAAa,sBAAsB;CAAC;CAAU;CAAQ;AAAS;AAuE/D,MAAM,gBAA0F;CAC9F,OAAO;CACP,MAAM;CACN,MAAM;CACN,SAAS;CACT,iBAAiB;AACnB;AAEA,MAAM,gBAA0F;CAC9F,GAAG;CACH,KAAK;CACL,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,MAAM,gBAAgB,UAAuD;CAC3E,IAAI,UAAU,KAAA,KAAa,OAAO,MAAM,KAAK,GAC3C,OAAO;CAIT,OAAQ,KAAK,MADG,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,CACtB,IAAI,EAAE,IAAI;AACrC;;AAGA,MAAa,yBAAyB,EACpC,QACA,YACuE;CACvE,IAAI,WAAW,QACb,OAAO;EACL,UAAU;EACV;CACF;CAGF,IAAI,QACF,OAAO;EACL,UAAU,cAAc;EACxB;CACF;CAGF,MAAM,WAAW,aAAa,KAAK;CACnC,OAAO;EACL;EACA,QAAQ,cAAc;CACxB;AACF;;;ACjHA,MAAM,qBAAqB;AAE3B,MAAM,gCAAgC;AACtC,MAAM,qBAAqB;AAC3B,MAAM,0BAA0B;AAChC,MAAM,4BAA4B;AAClC,MAAM,0BAA0B;AAChC,MAAM,4BAA4B;AAElC,MAAM,iBAAiB,QAA0B,kBAAuC;CACtF,IAAI,WAAW,SAAS,WAAW,aAAa,eAC9C,OAAO,EAAE,UAAU,IAAK;CAG1B,IAAI,WAAW,QACb,OAAO;EAAE,UAAU;EAAM,MAAM;GAAC;GAAM;GAAG;GAAM;EAAC;CAAW;CAG7D,OAAO;EAAE,UAAU;EAAM,MAAM;GAAC;GAAK;GAAG;GAAK;EAAC;CAAW;AAC3D;AAEA,MAAM,yBAAyB,QAA0B,kBAA2B;CAClF,IAAI,WAAW,SAAS,WAAW,aAAa,eAC9C,OAAO;CAGT,OAAO,WAAW,SAAS,0BAA0B;AACvD;AAEA,MAAM,oBAAoB,aAAqB;CAC7C,IAAI,WAAW,IACb,OAAO,IAAI,WAAW,WAAW;CAGnC,OAAO,KAAK,KAAK,WAAW,MAAM,IAAI;AACxC;AAEA,MAAM,eAAe,UAAkB,SAAiB;AAExD,MAAM,eAAe,UAAkB,WAAmB;CACxD,IAAI,YAAY,GACd,OAAO,IAAI,mBAAmB,GAAG;CAGnC,IAAI,YAAY,MAAM;EACpB,MAAM,WAAW,SAAS;EAE1B,OAAO;GACL,IAAI,qBAAqB,OAAO,GAAG;GACnC,IAAI,OAAO,GAAG,OAAO,SAAS,SAAS;GACvC,IAAI,OAAO,GAAG,OAAO,UAAU,SAAS;EAC1C,EAAE,KAAK,GAAG;CACZ;CAGA,MAAM,WADW,0BAA2B,MAAM,WAAY,6BAClC,KAAK,KAAM;CACvC,MAAM,IAAI,QAAQ,qBAAqB,SAAS,KAAK,IAAI,OAAO,GAAG,QAAQ,CAAC,CAAC;CAC7E,MAAM,IAAI,QAAQ,qBAAqB,SAAS,KAAK,IAAI,OAAO,GAAG,QAAQ,CAAC,CAAC;CAC7E,MAAM,eAAe,WAAW,KAAK,IAAI;CAEzC,OAAO;EACL,IAAI,mBAAmB,GAAG;EAC1B,IAAI,mBAAmB,GAAG,qBAAqB;EAC/C,IAAI,OAAO,GAAG,OAAO,KAAK,aAAa,KAAK,EAAE,GAAG;EACjD;CACF,EAAE,KAAK,GAAG;AACZ;AAEA,MAAM,gBAAgB,EACpB,OACA,OAAO,QACP,OACA,iBACsE;CACtE,MAAM,YAA6B;EACjC,GAAG,qBAAqB,MAAM,2BAA2B;EACzD,GAAG;CACL;CAEA,IAAI,OACF,UAAU,gCAAgC;CAG5C,IAAI,YACF,UAAU,gCAAgC;CAG5C,OAAO;AACT;AAEA,MAAM,mBAAmB,EACvB,kBACA,QACA,UACA,aAC6E;CAC7E,MAAM,oBAAoB,OAAsB,IAAI;CACpD,MAAM,sBAAsB,OAAe,QAAQ;CACnD,MAAM,CAAC,kBAAkB,uBAAuB,WAAW,aAAa,QAAQ;CAEhF,gBAAgB;EACd,MAAM,WAAW,sBAAsB,QAAQ,gBAAgB;EAC/D,MAAM,gBAAgB,oBAAoB;EAC1C,MAAM,gBAAgB,WAAW;EAEjC,IAAI,kBAAkB,YAAY,MAChC,qBAAqB,kBAAkB,OAAO;EAGhD,IAAI,aAAa,KAAK,kBAAkB,GAAG;GACzC,oBAAoB,UAAU;GAC9B,oBAAoB,QAAQ;GAC5B;EACF;EAEA,MAAM,YAAY,YAAY,IAAI;EAElC,MAAM,QAAQ,QAAgB;GAC5B,MAAM,UAAU,KAAK,KAAK,MAAM,aAAa,UAAU,CAAC;GACxD,MAAM,eAAe,gBAAgB,gBAAgB,iBAAiB,OAAO;GAE7E,oBAAoB,UAAU;GAC9B,oBAAoB,YAAY;GAEhC,IAAI,UAAU,GAAG;IACf,kBAAkB,UAAU,sBAAsB,IAAI;IACtD;GACF;GAEA,oBAAoB,UAAU;GAC9B,kBAAkB,UAAU;EAC9B;EAEA,kBAAkB,UAAU,sBAAsB,IAAI;EAEtD,aAAa;GACX,IAAI,kBAAkB,YAAY,MAChC,qBAAqB,kBAAkB,OAAO;EAElD;CACF,GAAG;EAAC;EAAkB;EAAQ;CAAQ,CAAC;CAEvC,OACE,oBAAC,QAAD;EACE,WAAU;EACV,GAAG,YAAY,kBAAkB,MAAM;EACvC,eAAY;CACb,CAAA;AAEL;AAEA,MAAM,aAAa,EACjB,kBACA,QACA,eAEA,oBAAC,EAAE,QAAH;CACE,SAAS;EAAE,SAAS,WAAW,IAAI,IAAI;EAAG,YAAY,WAAW;CAAI;CACrE,WAAU;CACV,IAAG;CACH,IAAG;CACH,SAAS;CACT,YAAW;CACX,GAAE;CACF,YAAY,cAAc,QAAQ,gBAAgB;AACnD,CAAA;AAGH,MAAM,iBAAiB,EACrB,kBACA,QACA,OACA,cAKA,oBAAC,OAAD;CAAK,eAAY;CAAO,WAAU;CAA+B,MAAK;CAAO,SAAQ;WAClF,MAAM,WAAW,SAChB,oBAAC,UAAD;EACE,WAAU;EACV,IAAG;EACH,IAAG;EACH,eAAY;EACZ,GAAG;CACJ,CAAA,IAED,qBAAA,UAAA,EAAA,UAAA;EACG,YAAY,SACX,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,UAAD;GACE,WAAU;GACV,IAAG;GACH,IAAG;GACH,eAAY;GACZ,GAAG;EACJ,CAAA,GACD,oBAAC,iBAAD;GACoB;GACV;GACR,UAAU,MAAM;GAChB,QAAQ;EACT,CAAA,CACD,EAAA,CAAA,IACA;EACH,YAAY,WACX,oBAAC,UAAD;GACE,WAAU;GACV,IAAG;GACH,IAAG;GACH,eAAY;GACZ,GAAG;EACJ,CAAA,IACC;EACH,YAAY,WACX,oBAAC,WAAD;GACoB;GACV;GACR,UAAU,MAAM;EACjB,CAAA,IACC;CACJ,EAAA,CAAA;AAED,CAAA;AAGP,MAAa,cAAc,EACzB,WACA,OACA,OACA,SAAS,UACT,OAAO,QACP,QACA,OACA,OAAO,WACP,YACA,OACA,UAAU,QACV,GAAG,YACkB;CACrB,MAAM,gBAAgB,iBAAiB;CACvC,MAAM,mBAAmB,QAAQ,aAAa;CAC9C,MAAM,QAAQ,sBAAsB;EAAE;EAAQ;CAAM,CAAC;CACrD,MAAM,YAAY,aAAa;EAAE;EAAO;EAAM;EAAO;CAAW,CAAC;CAEjE,OACE,oBAAC,QAAD;EACE,GAAI;EACJ,eAAa,QAAQ,KAAA,IAAY;EACjC,cAAY;EACZ,WAAW,eAAe,2BAA2B,SAAS;EAC9D,eAAa,WAAW,QAAQ,UAAU;EAC1C,iBAAe,MAAM,YAAY;EACjC,aAAU;EACV,eAAa,MAAM;EACnB,aAAW;EACX,gBAAc;EACd,MAAM,QAAQ,QAAQ,KAAA;EACtB,OAAO;YAEP,oBAAC,YAAD;GAAY,UAAU;aACpB,oBAAC,eAAD;IACoB;IACV;IACD;IACE;GACV,CAAA;EACS,CAAA;CACR,CAAA;AAEV"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/status-mark-types.ts","../src/status-mark.tsx"],"sourcesContent":["import type { HTMLAttributes } from \"react\";\n\nexport const STATUS_MARK_PROGRESS_STEPS = [\n \"null\",\n \"empty\",\n \"quarter\",\n \"half\",\n \"three-quarter\",\n \"full\",\n] as const;\n\nexport const STATUS_MARK_STATUSES = STATUS_MARK_PROGRESS_STEPS;\nexport const STATUS_MARK_PROGRESS_VALUES = [0, 25, 50, 75, 100] as const;\nexport const STATUS_MARK_TONES = [\"neutral\", \"accent\", \"muted\"] as const;\nexport const STATUS_MARK_VARIANTS = [\"fill\", \"border\"] as const;\nexport const STATUS_MARK_MOTIONS = [\"smooth\", \"snap\", \"reduced\"] as const;\n\nexport type StatusMarkMotion = (typeof STATUS_MARK_MOTIONS)[number] | false;\nexport type StatusMarkProgressStep = (typeof STATUS_MARK_PROGRESS_STEPS)[number];\nexport type StatusMarkProgressValue = (typeof STATUS_MARK_PROGRESS_VALUES)[number];\nexport type StatusMarkStatus = StatusMarkProgressStep;\nexport type StatusMarkTone = (typeof STATUS_MARK_TONES)[number];\nexport type StatusMarkVariant = (typeof STATUS_MARK_VARIANTS)[number];\n\nexport type ResolvedStatusProgress =\n | {\n progress: null;\n status: \"null\";\n }\n | {\n progress: StatusMarkProgressValue;\n status: Exclude<StatusMarkProgressStep, \"null\">;\n };\n\nexport interface StatusMarkProps extends Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /**\n * Active progress color. Overrides the selected visual `tone` when supplied.\n */\n color?: string;\n /**\n * Accessible label for the visual state. Omit only when adjacent text already\n * names the same progress and the mark should be decorative.\n */\n label?: string;\n /**\n * Transition preset for movement between progress steps.\n *\n * Default `\"smooth\"`.\n */\n motion?: StatusMarkMotion;\n /**\n * Named discrete progress step. Use `\"null\"` only when progress is explicitly\n * not yet known or measured.\n */\n status?: StatusMarkProgressStep;\n /**\n * Size token used for the mark dimensions.\n *\n * Default `\"base\"`.\n */\n size?: \"2xl\" | \"2xs\" | \"3xl\" | \"base\" | \"lg\" | \"sm\" | \"xl\" | \"xs\";\n /**\n * Visual emphasis treatment. Tone changes color only; progress shape carries\n * meaning.\n *\n * Default `\"neutral\"`.\n */\n tone?: StatusMarkTone;\n /**\n * Color used for inactive track or placeholder structure.\n */\n trackColor?: string;\n /**\n * Numeric progress input. Values are clamped from 0 to 100 and snapped to the\n * nearest discrete visual step: 0, 25, 50, 75, or 100.\n */\n value?: number;\n /**\n * Visual treatment for known progress. Null progress renders the same dashed\n * placeholder in every variant.\n *\n * Default `\"fill\"`.\n */\n variant?: StatusMarkVariant;\n}\n\nconst STEP_PROGRESS: Record<Exclude<StatusMarkProgressStep, \"null\">, StatusMarkProgressValue> = {\n empty: 0,\n full: 100,\n half: 50,\n quarter: 25,\n \"three-quarter\": 75,\n};\n\nconst PROGRESS_STEP: Record<StatusMarkProgressValue, Exclude<StatusMarkProgressStep, \"null\">> = {\n 0: \"empty\",\n 100: \"full\",\n 25: \"quarter\",\n 50: \"half\",\n 75: \"three-quarter\",\n};\n\nconst snapProgress = (value: number | undefined): StatusMarkProgressValue => {\n if (value === undefined || Number.isNaN(value)) {\n return 0;\n }\n\n const clamped = Math.min(100, Math.max(0, value));\n const snapped = Math.round(clamped / 25) * 25;\n\n switch (snapped) {\n case 25: {\n return 25;\n }\n case 50: {\n return 50;\n }\n case 75: {\n return 75;\n }\n case 100: {\n return 100;\n }\n default: {\n return 0;\n }\n }\n};\n\n/** Resolves named or numeric progress input into a discrete StatusMark step. */\nexport const resolveStatusProgress = ({\n status,\n value,\n}: Pick<StatusMarkProps, \"status\" | \"value\">): ResolvedStatusProgress => {\n if (status === \"null\") {\n return {\n progress: null,\n status,\n };\n }\n\n if (status !== undefined) {\n return {\n progress: STEP_PROGRESS[status],\n status,\n };\n }\n\n const progress = snapProgress(value);\n return {\n progress,\n status: PROGRESS_STEP[progress],\n };\n};\n","\"use client\";\n\nimport { easings } from \"@howells/motion\";\nimport { getSizeVariableStyle, joinClassNames } from \"@patternmode/system\";\nimport { useEffect, useReducer, useRef } from \"react\";\nimport type { CSSProperties } from \"react\";\nimport { domMax, LazyMotion, m, useReducedMotion } from \"motion/react\";\nimport type { Transition } from \"motion/react\";\n\nimport { resolveStatusProgress } from \"./status-mark-types\";\nimport type {\n ResolvedStatusProgress,\n StatusMarkMotion,\n StatusMarkProgressValue,\n StatusMarkProps,\n} from \"./status-mark-types\";\n\ntype StatusMarkStyle = CSSProperties & Record<`--${string}`, string | number | undefined>;\ninterface MotionPartProps {\n hasReducedMotion: boolean;\n motion: StatusMarkMotion;\n}\n\nconst STATUS_MARK_RADIUS = 8;\nconst STATUS_MARK_STROKE_WIDTH = 1.8;\nconst BORDERLESS_STATUS_MARK_RADIUS = STATUS_MARK_RADIUS + STATUS_MARK_STROKE_WIDTH / 2;\nconst STATUS_MARK_CENTER = 12;\nconst STATUS_MARK_START_ANGLE = -90;\nconst STATUS_MARK_FULL_PROGRESS = 100;\nconst STATUS_SNAP_DURATION_MS = 160;\nconst STATUS_SMOOTH_DURATION_MS = 280;\n\nconst getTransition = (motion: StatusMarkMotion, reducedMotion: boolean): Transition => {\n if (motion === false || motion === \"reduced\" || reducedMotion) {\n return { duration: 0.01 };\n }\n\n if (motion === \"snap\") {\n return { duration: 0.16, ease: easings.snappy };\n }\n\n return { duration: 0.28, ease: easings.smooth };\n};\n\nconst getFillMotionDuration = (motion: StatusMarkMotion, reducedMotion: boolean) => {\n if (motion === false || motion === \"reduced\" || reducedMotion) {\n return 0;\n }\n\n return motion === \"snap\" ? STATUS_SNAP_DURATION_MS : STATUS_SMOOTH_DURATION_MS;\n};\n\nconst easeFillProgress = (progress: number) => {\n if (progress < 0.5) {\n return 4 * progress * progress * progress;\n }\n\n return 1 - (-2 * progress + 2) ** 3 / 2;\n};\n\nconst setProgress = (_current: number, next: number) => next;\n\nconst getFillPath = (progress: number, radius: number) => {\n if (progress <= 0) {\n return `M${STATUS_MARK_CENTER} ${STATUS_MARK_CENTER}`;\n }\n\n if (progress >= 99.9) {\n const diameter = radius * 2;\n\n return [\n `M${STATUS_MARK_CENTER - radius} ${STATUS_MARK_CENTER}`,\n `a${radius} ${radius} 0 1 0 ${diameter} 0`,\n `a${radius} ${radius} 0 1 0 -${diameter} 0`,\n ].join(\" \");\n }\n\n const endAngle = STATUS_MARK_START_ANGLE + (360 * progress) / STATUS_MARK_FULL_PROGRESS;\n const radians = (endAngle * Math.PI) / 180;\n const x = Number((STATUS_MARK_CENTER + radius * Math.cos(radians)).toFixed(3));\n const y = Number((STATUS_MARK_CENTER + radius * Math.sin(radians)).toFixed(3));\n const largeArcFlag = progress > 50 ? 1 : 0;\n\n return [\n `M${STATUS_MARK_CENTER} ${STATUS_MARK_CENTER}`,\n `L${STATUS_MARK_CENTER} ${STATUS_MARK_CENTER - radius}`,\n `A${radius} ${radius} 0 ${largeArcFlag} 1 ${x} ${y}`,\n \"Z\",\n ].join(\" \");\n};\n\nconst getRootStyle = ({\n color,\n size = \"base\",\n style,\n trackColor,\n}: Pick<StatusMarkProps, \"color\" | \"size\" | \"style\" | \"trackColor\">) => {\n const rootStyle: StatusMarkStyle = {\n ...getSizeVariableStyle(size, \"--patternmode-status-size\"),\n ...style,\n };\n\n if (color !== undefined && color !== \"\") {\n rootStyle[\"--patternmode-status-color\"] = color;\n }\n\n if (trackColor !== undefined && trackColor !== \"\") {\n rootStyle[\"--patternmode-status-track\"] = trackColor;\n }\n\n return rootStyle;\n};\n\nconst StatusFillSweep = ({\n hasReducedMotion,\n motion,\n progress,\n radius,\n}: MotionPartProps & { progress: StatusMarkProgressValue; radius: number }) => {\n const animationFrameRef = useRef<number | null>(null);\n const renderedProgressRef = useRef<number>(progress);\n const [renderedProgress, setRenderedProgress] = useReducer(setProgress, progress);\n\n useEffect(() => {\n const cancelFillAnimation = () => {\n if (animationFrameRef.current !== null) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n };\n const duration = getFillMotionDuration(motion, hasReducedMotion);\n const startProgress = renderedProgressRef.current;\n const progressDelta = progress - startProgress;\n\n cancelFillAnimation();\n\n if (duration === 0 || progressDelta === 0) {\n renderedProgressRef.current = progress;\n setRenderedProgress(progress);\n return cancelFillAnimation;\n }\n\n const startTime = performance.now();\n\n const tick = (now: number) => {\n const elapsed = Math.min((now - startTime) / duration, 1);\n const nextProgress = startProgress + progressDelta * easeFillProgress(elapsed);\n\n renderedProgressRef.current = nextProgress;\n setRenderedProgress(nextProgress);\n\n if (elapsed < 1) {\n animationFrameRef.current = requestAnimationFrame(tick);\n return;\n }\n\n renderedProgressRef.current = progress;\n animationFrameRef.current = null;\n };\n\n animationFrameRef.current = requestAnimationFrame(tick);\n\n return cancelFillAnimation;\n }, [hasReducedMotion, motion, progress]);\n\n return (\n <path\n className=\"patternmode-status-mark__fill-sweep\"\n d={getFillPath(renderedProgress, radius)}\n data-testid=\"status-mark-fill-sweep\"\n />\n );\n};\n\nconst StatusArc = ({\n hasReducedMotion,\n motion,\n progress,\n}: MotionPartProps & { progress: StatusMarkProgressValue }) => (\n <m.circle\n animate={{ opacity: progress > 0 ? 1 : 0, pathLength: progress / 100 }}\n className=\"patternmode-status-mark__arc\"\n cx=\"12\"\n cy=\"12\"\n initial={false}\n pathLength=\"1\"\n r=\"8\"\n transition={getTransition(motion, hasReducedMotion)}\n />\n);\n\nconst StatusMarkSvg = ({\n hasReducedMotion,\n motion,\n state,\n variant,\n}: MotionPartProps & {\n state: ResolvedStatusProgress;\n variant: NonNullable<StatusMarkProps[\"variant\"]>;\n}) => (\n <svg aria-hidden=\"true\" className=\"patternmode-status-mark__svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n {state.status === \"null\" ? (\n <circle\n className=\"patternmode-status-mark__track patternmode-status-mark__track--null\"\n cx=\"12\"\n cy=\"12\"\n data-testid=\"status-mark-null\"\n r={STATUS_MARK_RADIUS}\n />\n ) : (\n <>\n {variant === \"fill\" ? (\n <>\n <circle\n className=\"patternmode-status-mark__disc\"\n cx=\"12\"\n cy=\"12\"\n data-testid=\"status-mark-fill\"\n r={BORDERLESS_STATUS_MARK_RADIUS}\n />\n <StatusFillSweep\n hasReducedMotion={hasReducedMotion}\n motion={motion}\n progress={state.progress}\n radius={BORDERLESS_STATUS_MARK_RADIUS}\n />\n </>\n ) : null}\n {variant === \"border\" ? (\n <circle\n className=\"patternmode-status-mark__track\"\n cx=\"12\"\n cy=\"12\"\n data-testid=\"status-mark-border\"\n r={STATUS_MARK_RADIUS}\n />\n ) : null}\n {variant === \"border\" ? (\n <StatusArc\n hasReducedMotion={hasReducedMotion}\n motion={motion}\n progress={state.progress}\n />\n ) : null}\n </>\n )}\n </svg>\n);\n\nexport const StatusMark = ({\n className,\n color,\n label,\n motion = \"smooth\",\n size = \"base\",\n status,\n style,\n tone = \"neutral\",\n trackColor,\n value,\n variant = \"fill\",\n ...props\n}: StatusMarkProps) => {\n const reducedMotion = useReducedMotion();\n const hasReducedMotion = Boolean(reducedMotion);\n const state = resolveStatusProgress({ status, value });\n const rootStyle = getRootStyle({ color, size, style, trackColor });\n const hasLabel = label !== undefined && label !== \"\";\n\n return (\n <span\n {...props}\n aria-hidden={hasLabel ? undefined : true}\n aria-label={label}\n className={joinClassNames(\"patternmode-status-mark\", className)}\n data-motion={motion === false ? \"false\" : motion}\n data-progress={state.progress ?? \"null\"}\n data-slot=\"status-mark\"\n data-status={state.status}\n data-tone={tone}\n data-variant={variant}\n role={hasLabel ? \"img\" : undefined}\n style={rootStyle}\n >\n <LazyMotion features={domMax}>\n <StatusMarkSvg\n hasReducedMotion={hasReducedMotion}\n motion={motion}\n state={state}\n variant={variant}\n />\n </LazyMotion>\n </span>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status-mark-types.d.ts","sourceRoot":"","sources":["../src/status-mark-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,eAAO,MAAM,0BAA0B,wEAO7B,CAAC;AAEX,eAAO,MAAM,oBAAoB,wEAA6B,CAAC;AAC/D,eAAO,MAAM,2BAA2B,+BAAgC,CAAC;AACzE,eAAO,MAAM,iBAAiB,yCAA0C,CAAC;AACzE,eAAO,MAAM,oBAAoB,6BAA8B,CAAC;AAChE,eAAO,MAAM,mBAAmB,wCAAyC,CAAC;AAE1E,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;AAC5E,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AACjF,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC;AACnF,MAAM,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AACtD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAChE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,MAAM,MAAM,sBAAsB,GAC9B;IACE,QAAQ,EAAE,IAAI,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IACE,QAAQ,EAAE,uBAAuB,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC;CACjD,CAAC;AAEN,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,EAAE,UAAU,CAAC;IACxF;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B;;;OAGG;IACH,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAChC;;;;OAIG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAClE;;;;;OAKG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;
|
|
1
|
+
{"version":3,"file":"status-mark-types.d.ts","sourceRoot":"","sources":["../src/status-mark-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,eAAO,MAAM,0BAA0B,wEAO7B,CAAC;AAEX,eAAO,MAAM,oBAAoB,wEAA6B,CAAC;AAC/D,eAAO,MAAM,2BAA2B,+BAAgC,CAAC;AACzE,eAAO,MAAM,iBAAiB,yCAA0C,CAAC;AACzE,eAAO,MAAM,oBAAoB,6BAA8B,CAAC;AAChE,eAAO,MAAM,mBAAmB,wCAAyC,CAAC;AAE1E,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;AAC5E,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AACjF,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC;AACnF,MAAM,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AACtD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAChE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,MAAM,MAAM,sBAAsB,GAC9B;IACE,QAAQ,EAAE,IAAI,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IACE,QAAQ,EAAE,uBAAuB,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC;CACjD,CAAC;AAEN,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,EAAE,UAAU,CAAC;IACxF;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B;;;OAGG;IACH,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAChC;;;;OAIG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAClE;;;;;OAKG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;AA6CD,gFAAgF;AAChF,eAAO,MAAM,qBAAqB,GAAI,oBAGnC,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAG,sBAoB9C,CAAC"}
|
package/dist/status-mark.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { StatusMarkProps } from "./status-mark-types";
|
|
2
|
-
export declare const StatusMark: ({ className, color, label, motion, size, status, style, tone, trackColor, value, variant, ...props }: StatusMarkProps) => import("react
|
|
2
|
+
export declare const StatusMark: ({ className, color, label, motion, size, status, style, tone, trackColor, value, variant, ...props }: StatusMarkProps) => import("react").JSX.Element;
|
|
3
3
|
//# sourceMappingURL=status-mark.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status-mark.d.ts","sourceRoot":"","sources":["../src/status-mark.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"status-mark.d.ts","sourceRoot":"","sources":["../src/status-mark.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAIV,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAyO7B,eAAO,MAAM,UAAU,GAAI,sGAaxB,eAAe,gCAgCjB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patternmode/status",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Animated discrete status marks for Patternmode interfaces.",
|
|
6
6
|
"keywords": [
|
|
@@ -41,40 +41,27 @@
|
|
|
41
41
|
"publishConfig": {
|
|
42
42
|
"access": "public"
|
|
43
43
|
},
|
|
44
|
-
"scripts": {
|
|
45
|
-
"build": "tsdown && tsc --emitDeclarationOnly --declaration --declarationMap --outDir dist --noEmit false && pnpm build:styles",
|
|
46
|
-
"build:styles": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify",
|
|
47
|
-
"clean": "rm -rf dist .turbo",
|
|
48
|
-
"dev": "concurrently \"pnpm dev:js\" \"pnpm dev:types\" \"pnpm dev:styles\"",
|
|
49
|
-
"dev:js": "tsdown --watch",
|
|
50
|
-
"dev:styles": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --watch",
|
|
51
|
-
"dev:types": "tsc --emitDeclarationOnly --declaration --declarationMap --outDir dist --noEmit false --watch --preserveWatchOutput",
|
|
52
|
-
"lint": "howells-ox-check .",
|
|
53
|
-
"lint:fix": "howells-ox-fix .",
|
|
54
|
-
"prepack": "pnpm build",
|
|
55
|
-
"test": "vitest run",
|
|
56
|
-
"typecheck": "tsc --noEmit"
|
|
57
|
-
},
|
|
58
44
|
"dependencies": {
|
|
59
|
-
"
|
|
60
|
-
"motion": "
|
|
45
|
+
"motion": "^12.40.0",
|
|
46
|
+
"@howells/motion": "0.1.0",
|
|
47
|
+
"@patternmode/system": "0.3.0"
|
|
61
48
|
},
|
|
62
49
|
"devDependencies": {
|
|
63
|
-
"@howells/lint": "^0.
|
|
64
|
-
"@howells/typescript-config": "^0.1.
|
|
50
|
+
"@howells/lint": "^0.5.0",
|
|
51
|
+
"@howells/typescript-config": "^0.1.6",
|
|
65
52
|
"@tailwindcss/cli": "^4.3.0",
|
|
66
53
|
"@testing-library/jest-dom": "^6.9.1",
|
|
67
54
|
"@testing-library/react": "^16.3.2",
|
|
68
|
-
"@types/react": "^19.2.
|
|
55
|
+
"@types/react": "^19.2.17",
|
|
69
56
|
"@types/react-dom": "^19.2.3",
|
|
70
57
|
"concurrently": "^9.2.1",
|
|
71
58
|
"jsdom": "^29.1.1",
|
|
72
|
-
"react": "^19.2.
|
|
73
|
-
"react-dom": "^19.2.
|
|
59
|
+
"react": "^19.2.7",
|
|
60
|
+
"react-dom": "^19.2.7",
|
|
74
61
|
"tailwindcss": "^4.3.0",
|
|
75
62
|
"tsdown": "^0.22.0",
|
|
76
63
|
"typescript": "^6.0.3",
|
|
77
|
-
"vitest": "^4.1.
|
|
64
|
+
"vitest": "^4.1.8"
|
|
78
65
|
},
|
|
79
66
|
"peerDependencies": {
|
|
80
67
|
"react": "^19.0.0",
|
|
@@ -82,5 +69,18 @@
|
|
|
82
69
|
},
|
|
83
70
|
"engines": {
|
|
84
71
|
"node": ">=20"
|
|
72
|
+
},
|
|
73
|
+
"scripts": {
|
|
74
|
+
"build": "tsdown && tsc --emitDeclarationOnly --declaration --declarationMap --outDir dist --noEmit false && pnpm build:styles",
|
|
75
|
+
"build:styles": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify",
|
|
76
|
+
"clean": "rm -rf dist .turbo",
|
|
77
|
+
"dev": "concurrently \"pnpm dev:js\" \"pnpm dev:types\" \"pnpm dev:styles\"",
|
|
78
|
+
"dev:js": "tsdown --watch",
|
|
79
|
+
"dev:styles": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --watch",
|
|
80
|
+
"dev:types": "tsc --emitDeclarationOnly --declaration --declarationMap --outDir dist --noEmit false --watch --preserveWatchOutput",
|
|
81
|
+
"lint": "howells-check .",
|
|
82
|
+
"lint:fix": "howells-fix .",
|
|
83
|
+
"test": "vitest run",
|
|
84
|
+
"typecheck": "tsc --noEmit"
|
|
85
85
|
}
|
|
86
|
-
}
|
|
86
|
+
}
|