@k8o/arte-odyssey 8.0.2 → 9.0.0
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/components/buttons/icon-button/icon-button.mjs +6 -17
- package/dist/components/data-display/accordion/context.d.mts +1 -1
- package/dist/components/data-display/accordion/context.mjs +3 -12
- package/dist/components/data-display/code/code.mjs +1 -1
- package/dist/{helpers/color → components/data-display/code}/find-all-colors.d.mts +1 -1
- package/dist/{helpers/color → components/data-display/code}/find-all-colors.mjs +1 -1
- package/dist/components/feedback/progress/progress.mjs +1 -1
- package/dist/components/feedback/toast/context.d.mts +2 -2
- package/dist/components/feedback/toast/context.mjs +6 -7
- package/dist/components/form/autocomplete/autocomplete.mjs +14 -13
- package/dist/components/form/checkbox/checkbox.mjs +7 -4
- package/dist/components/form/checkbox-card/checkbox-card.mjs +8 -7
- package/dist/components/form/checkbox-group/index.d.mts +3 -3
- package/dist/components/form/file-field/file-field.mjs +4 -10
- package/dist/{helpers/number → components/form/number-field}/cast.d.mts +1 -1
- package/dist/{helpers/number → components/form/number-field}/cast.mjs +2 -2
- package/dist/components/form/number-field/number-field.mjs +20 -19
- package/dist/components/form/radio/radio.mjs +6 -4
- package/dist/components/form/radio-card/radio-card.mjs +7 -5
- package/dist/components/form/switch/switch.mjs +7 -4
- package/dist/components/icons/index.d.mts +3 -2
- package/dist/components/icons/index.mjs +3 -2
- package/dist/components/icons/logo.mjs +3 -3
- package/dist/components/icons/lucide.d.mts +2 -1
- package/dist/components/icons/lucide.mjs +6 -2
- package/dist/components/icons/qiita.mjs +4 -4
- package/dist/components/icons/twitter.mjs +1 -1
- package/dist/components/icons/vertical-writing.d.mts +7 -0
- package/dist/components/icons/vertical-writing.mjs +25 -0
- package/dist/components/index.d.mts +3 -2
- package/dist/components/index.mjs +3 -2
- package/dist/components/navigation/anchor/anchor.mjs +1 -2
- package/dist/components/navigation/tabs/tabs.mjs +4 -13
- package/dist/components/overlays/dialog/dialog.mjs +3 -7
- package/dist/components/overlays/dropdown-menu/hooks.d.mts +2 -3
- package/dist/components/overlays/dropdown-menu/hooks.mjs +4 -9
- package/dist/components/overlays/list-box/hooks.d.mts +0 -1
- package/dist/components/overlays/list-box/hooks.mjs +3 -8
- package/dist/components/overlays/popover/hooks.d.mts +1 -3
- package/dist/components/overlays/popover/hooks.mjs +3 -8
- package/dist/components/overlays/tooltip/tooltip.mjs +19 -6
- package/dist/helpers/chain.d.mts +5 -0
- package/dist/helpers/chain.mjs +29 -0
- package/dist/helpers/create-safe-context.d.mts +7 -0
- package/dist/helpers/create-safe-context.mjs +13 -0
- package/dist/helpers/index.d.mts +5 -8
- package/dist/helpers/index.mjs +5 -8
- package/dist/helpers/merge-props.d.mts +6 -0
- package/dist/helpers/merge-props.mjs +56 -0
- package/dist/hooks/click-away/index.mjs +1 -1
- package/dist/index.d.mts +7 -9
- package/dist/index.mjs +7 -9
- package/dist/internal/clamp.d.mts +4 -0
- package/dist/internal/clamp.mjs +15 -0
- package/dist/{helpers/number → internal}/to-precision.d.mts +1 -1
- package/dist/{helpers/number → internal}/to-precision.mjs +1 -1
- package/package.json +5 -5
- package/dist/helpers/is-internal-route.d.mts +0 -4
- package/dist/helpers/is-internal-route.mjs +0 -12
- package/dist/helpers/number/between.d.mts +0 -4
- package/dist/helpers/number/between.mjs +0 -15
- package/dist/helpers/number/commalize.d.mts +0 -4
- package/dist/helpers/number/commalize.mjs +0 -20
- package/dist/helpers/number/index.d.mts +0 -5
- package/dist/helpers/number/index.mjs +0 -5
- package/dist/helpers/uuid-v4.d.mts +0 -4
- package/dist/helpers/uuid-v4.mjs +0 -28
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { usePlacement, usePopoverContext } from "../popover/hooks.mjs";
|
|
3
3
|
import { Popover } from "../popover/popover.mjs";
|
|
4
|
-
import { useMemo } from "react";
|
|
4
|
+
import { useCallback, useMemo, useSyncExternalStore } from "react";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
//#region src/components/overlays/tooltip/tooltip.tsx
|
|
7
|
+
const HOVER_QUERY = "(hover: hover)";
|
|
8
|
+
const useCanHover = () => {
|
|
9
|
+
return useSyncExternalStore(useCallback((cb) => {
|
|
10
|
+
const mql = window.matchMedia(HOVER_QUERY);
|
|
11
|
+
mql.addEventListener("change", cb);
|
|
12
|
+
return () => {
|
|
13
|
+
mql.removeEventListener("change", cb);
|
|
14
|
+
};
|
|
15
|
+
}, []), () => window.matchMedia(HOVER_QUERY).matches, () => true);
|
|
16
|
+
};
|
|
17
|
+
const noop = () => {};
|
|
7
18
|
const useTooltipTriggerProps = () => {
|
|
8
19
|
const popover = usePopoverContext();
|
|
20
|
+
const canHover = useCanHover();
|
|
9
21
|
return useMemo(() => ({
|
|
10
22
|
ref: popover.setTriggerRef,
|
|
11
|
-
onMouseEnter: popover.onOpen,
|
|
12
|
-
onMouseLeave: popover.onClose,
|
|
23
|
+
onMouseEnter: canHover ? popover.onOpen : noop,
|
|
24
|
+
onMouseLeave: canHover ? popover.onClose : noop,
|
|
13
25
|
onFocus: (e) => {
|
|
14
26
|
if (e.target.matches(":focus-visible")) popover.onOpen();
|
|
15
27
|
},
|
|
16
28
|
onBlur: popover.onClose,
|
|
17
29
|
"aria-describedby": popover.isOpen ? `${popover.rootId}_list` : void 0
|
|
18
|
-
}), [popover]);
|
|
30
|
+
}), [popover, canHover]);
|
|
19
31
|
};
|
|
20
32
|
const Root = ({ children, placement = "bottom" }) => /* @__PURE__ */ jsx(Popover.Root, {
|
|
21
33
|
closeOnClickAway: false,
|
|
@@ -28,6 +40,7 @@ const Trigger = ({ renderItem }) => renderItem(useTooltipTriggerProps());
|
|
|
28
40
|
const Content = ({ children }) => {
|
|
29
41
|
const placement = usePlacement();
|
|
30
42
|
const popover = usePopoverContext();
|
|
43
|
+
const canHover = useCanHover();
|
|
31
44
|
const translate = {
|
|
32
45
|
top: { translateY: 5 },
|
|
33
46
|
bottom: { translateY: -5 },
|
|
@@ -55,8 +68,8 @@ const Content = ({ children }) => {
|
|
|
55
68
|
id,
|
|
56
69
|
onBlur: popover.onClose,
|
|
57
70
|
onFocus: popover.onOpen,
|
|
58
|
-
onMouseEnter: popover.onOpen,
|
|
59
|
-
onMouseLeave: popover.onClose,
|
|
71
|
+
onMouseEnter: canHover ? popover.onOpen : noop,
|
|
72
|
+
onMouseLeave: canHover ? popover.onClose : noop,
|
|
60
73
|
ref,
|
|
61
74
|
role: "tooltip",
|
|
62
75
|
children
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//#region src/helpers/chain.ts
|
|
2
|
+
const chain = (...callbacks) => (...args) => {
|
|
3
|
+
for (const callback of callbacks) callback?.(...args);
|
|
4
|
+
};
|
|
5
|
+
if (import.meta.vitest) describe("chain", () => {
|
|
6
|
+
it("渡されたコールバックを順番に呼び出す", () => {
|
|
7
|
+
const calls = [];
|
|
8
|
+
chain(() => calls.push(1), () => calls.push(2), () => calls.push(3))();
|
|
9
|
+
expect(calls).toEqual([
|
|
10
|
+
1,
|
|
11
|
+
2,
|
|
12
|
+
3
|
|
13
|
+
]);
|
|
14
|
+
});
|
|
15
|
+
it("引数を全てのコールバックに渡す", () => {
|
|
16
|
+
const fn1 = vi.fn();
|
|
17
|
+
const fn2 = vi.fn();
|
|
18
|
+
chain(fn1, fn2)("a", 1);
|
|
19
|
+
expect(fn1).toHaveBeenCalledWith("a", 1);
|
|
20
|
+
expect(fn2).toHaveBeenCalledWith("a", 1);
|
|
21
|
+
});
|
|
22
|
+
it("undefinedのコールバックはスキップする", () => {
|
|
23
|
+
const fn = vi.fn();
|
|
24
|
+
chain(void 0, fn, void 0)();
|
|
25
|
+
expect(fn).toHaveBeenCalledOnce();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
//#endregion
|
|
29
|
+
export { chain };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Context } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/helpers/create-safe-context.d.ts
|
|
4
|
+
type CreateSafeContextReturn<T> = readonly [Context<T | null>, () => T];
|
|
5
|
+
declare const createSafeContext: <T>(errorMessage: string) => CreateSafeContextReturn<T>;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { createSafeContext };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createContext, use } from "react";
|
|
2
|
+
//#region src/helpers/create-safe-context.ts
|
|
3
|
+
const createSafeContext = (errorMessage) => {
|
|
4
|
+
const Context = createContext(null);
|
|
5
|
+
const useSafeContext = () => {
|
|
6
|
+
const value = use(Context);
|
|
7
|
+
if (value === null) throw new Error(errorMessage);
|
|
8
|
+
return value;
|
|
9
|
+
};
|
|
10
|
+
return [Context, useSafeContext];
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { createSafeContext };
|
package/dist/helpers/index.d.mts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
+
import { chain } from "./chain.mjs";
|
|
1
2
|
import { cn } from "./cn.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import { commalize } from "./number/commalize.mjs";
|
|
7
|
-
import { toPrecision } from "./number/to-precision.mjs";
|
|
8
|
-
import { uuidV4 } from "./uuid-v4.mjs";
|
|
9
|
-
export { between, cast, cn, commalize, findAllColors, isInternalRoute, toPrecision, uuidV4 };
|
|
3
|
+
import { createSafeContext } from "./create-safe-context.mjs";
|
|
4
|
+
import { mergeProps } from "./merge-props.mjs";
|
|
5
|
+
import { mergeRefs } from "./merge-refs.mjs";
|
|
6
|
+
export { chain, cn, createSafeContext, mergeProps, mergeRefs };
|
package/dist/helpers/index.mjs
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { cn } from "./cn.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import { commalize } from "./number/commalize.mjs";
|
|
8
|
-
import { isInternalRoute } from "./is-internal-route.mjs";
|
|
9
|
-
export { between, cast, cn, commalize, findAllColors, isInternalRoute, toPrecision, uuidV4 };
|
|
2
|
+
import { createSafeContext } from "./create-safe-context.mjs";
|
|
3
|
+
import { chain } from "./chain.mjs";
|
|
4
|
+
import { mergeRefs } from "./merge-refs.mjs";
|
|
5
|
+
import { mergeProps } from "./merge-props.mjs";
|
|
6
|
+
export { chain, cn, createSafeContext, mergeProps, mergeRefs };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
//#region src/helpers/merge-props.d.ts
|
|
2
|
+
type Props = Record<string, unknown>;
|
|
3
|
+
type MergedProps<A, B> = Omit<A, keyof B> & B;
|
|
4
|
+
declare const mergeProps: <A extends Props, B extends Props>(base: A, override: B) => MergedProps<A, B>;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { mergeProps };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { cn } from "./cn.mjs";
|
|
2
|
+
import { chain } from "./chain.mjs";
|
|
3
|
+
//#region src/helpers/merge-props.ts
|
|
4
|
+
const isEventHandler = (key, value) => typeof value === "function" && key.startsWith("on") && key.length > 2 && key[2] === (key[2]?.toUpperCase() ?? "");
|
|
5
|
+
const mergeProps = (base, override) => {
|
|
6
|
+
const result = { ...base };
|
|
7
|
+
for (const key of Object.keys(override)) {
|
|
8
|
+
const baseValue = base[key];
|
|
9
|
+
const overrideValue = override[key];
|
|
10
|
+
if (key === "className") result[key] = cn(baseValue, overrideValue);
|
|
11
|
+
else if (key === "style") result[key] = {
|
|
12
|
+
...baseValue,
|
|
13
|
+
...overrideValue
|
|
14
|
+
};
|
|
15
|
+
else if (isEventHandler(key, baseValue) && isEventHandler(key, overrideValue)) result[key] = chain(baseValue, overrideValue);
|
|
16
|
+
else if (overrideValue !== void 0) result[key] = overrideValue;
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
};
|
|
20
|
+
if (import.meta.vitest) describe("mergeProps", () => {
|
|
21
|
+
it("classNameをcnでマージする", () => {
|
|
22
|
+
const merged = mergeProps({ className: "p-2 text-fg-base" }, { className: "text-fg-mute" });
|
|
23
|
+
expect(merged.className).toBe("p-2 text-fg-mute");
|
|
24
|
+
});
|
|
25
|
+
it("styleを浅くマージする", () => {
|
|
26
|
+
const merged = mergeProps({ style: {
|
|
27
|
+
color: "red",
|
|
28
|
+
fontSize: 12
|
|
29
|
+
} }, { style: { color: "blue" } });
|
|
30
|
+
expect(merged.style).toEqual({
|
|
31
|
+
color: "blue",
|
|
32
|
+
fontSize: 12
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
it("onClickなどのイベントハンドラを連結する", () => {
|
|
36
|
+
const calls = [];
|
|
37
|
+
mergeProps({ onClick: () => calls.push("a") }, { onClick: () => calls.push("b") }).onClick();
|
|
38
|
+
expect(calls).toEqual(["a", "b"]);
|
|
39
|
+
});
|
|
40
|
+
it("それ以外のpropsは後勝ちで上書きする", () => {
|
|
41
|
+
const merged = mergeProps({
|
|
42
|
+
id: "a",
|
|
43
|
+
disabled: true
|
|
44
|
+
}, { id: "b" });
|
|
45
|
+
expect(merged).toEqual({
|
|
46
|
+
id: "b",
|
|
47
|
+
disabled: true
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
it("overrideがundefinedの場合はbaseの値を保持する", () => {
|
|
51
|
+
const merged = mergeProps({ id: "a" }, { id: void 0 });
|
|
52
|
+
expect(merged.id).toBe("a");
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
//#endregion
|
|
56
|
+
export { mergeProps };
|
|
@@ -9,7 +9,7 @@ const useClickAway = (ref, callback, enabled = true) => {
|
|
|
9
9
|
if (element && e.target instanceof Node && !element.contains(e.target)) callback(e);
|
|
10
10
|
};
|
|
11
11
|
document.addEventListener("mousedown", handler);
|
|
12
|
-
document.addEventListener("touchstart", handler);
|
|
12
|
+
document.addEventListener("touchstart", handler, { passive: true });
|
|
13
13
|
return () => {
|
|
14
14
|
document.removeEventListener("mousedown", handler);
|
|
15
15
|
document.removeEventListener("touchstart", handler);
|
package/dist/index.d.mts
CHANGED
|
@@ -36,9 +36,10 @@ import { Textarea } from "./components/form/textarea/textarea.mjs";
|
|
|
36
36
|
import { ArteOdyssey } from "./components/icons/arte-odyssey.mjs";
|
|
37
37
|
import { GitHubIcon } from "./components/icons/github-mark.mjs";
|
|
38
38
|
import { Logo, LogoIcon } from "./components/icons/logo.mjs";
|
|
39
|
-
import { AIIcon, AccessibilityIcon, AlertIcon, AtomIcon, BadIcon, BlogIcon, BoringIcon, CheckIcon, ChevronIcon, CloseIcon, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, DifficultIcon, EasyIcon, ExternalLinkIcon, FormIcon, GoodIcon, HistoryIcon, InformativeIcon, InterestingIcon, LightModeIcon, LinkIcon, ListIcon, LocationIcon, MailIcon, MinusIcon, MixedColorIcon, NavigationMenuIcon, NewsIcon, PaletteIcon, PlusIcon, PrepareIcon, PublishDateIcon, RSSIcon, SendIcon, ShallowIcon, ShieldCheckIcon, SlideIcon, SparklesIcon, SubscribeIcon, TableIcon, TagIcon, UpdateDateIcon, ViewIcon, ViewOffIcon } from "./components/icons/lucide.mjs";
|
|
39
|
+
import { AIIcon, AccessibilityIcon, AlertIcon, AtomIcon, BadIcon, BlogIcon, BoringIcon, CheckIcon, ChevronIcon, CloseIcon, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, DifficultIcon, EasyIcon, ExternalLinkIcon, FormIcon, GoodIcon, HistoryIcon, HorizontalWritingIcon, InformativeIcon, InterestingIcon, LightModeIcon, LinkIcon, ListIcon, LocationIcon, MailIcon, MinusIcon, MixedColorIcon, NavigationMenuIcon, NewsIcon, PaletteIcon, PlusIcon, PrepareIcon, PublishDateIcon, RSSIcon, SendIcon, ShallowIcon, ShieldCheckIcon, SlideIcon, SparklesIcon, SubscribeIcon, TableIcon, TagIcon, UpdateDateIcon, ViewIcon, ViewOffIcon } from "./components/icons/lucide.mjs";
|
|
40
40
|
import { QiitaIcon } from "./components/icons/qiita.mjs";
|
|
41
41
|
import { TwitterIcon } from "./components/icons/twitter.mjs";
|
|
42
|
+
import { VerticalWritingIcon } from "./components/icons/vertical-writing.mjs";
|
|
42
43
|
import { ScrollLinked } from "./components/layout/scroll-linked/scroll-linked.mjs";
|
|
43
44
|
import { Separator } from "./components/layout/separator/separator.mjs";
|
|
44
45
|
import { Anchor } from "./components/navigation/anchor/anchor.mjs";
|
|
@@ -54,14 +55,11 @@ import { useOpenContext } from "./components/overlays/popover/hooks.mjs";
|
|
|
54
55
|
import { Popover } from "./components/overlays/popover/popover.mjs";
|
|
55
56
|
import { ArteOdysseyProvider } from "./components/providers/arte-odyssey-provider.mjs";
|
|
56
57
|
import { PortalRootProvider, usePortalRoot } from "./components/providers/portal-root.mjs";
|
|
58
|
+
import { chain } from "./helpers/chain.mjs";
|
|
57
59
|
import { cn } from "./helpers/cn.mjs";
|
|
58
|
-
import {
|
|
59
|
-
import {
|
|
60
|
-
import {
|
|
61
|
-
import { cast } from "./helpers/number/cast.mjs";
|
|
62
|
-
import { commalize } from "./helpers/number/commalize.mjs";
|
|
63
|
-
import { toPrecision } from "./helpers/number/to-precision.mjs";
|
|
64
|
-
import { uuidV4 } from "./helpers/uuid-v4.mjs";
|
|
60
|
+
import { createSafeContext } from "./helpers/create-safe-context.mjs";
|
|
61
|
+
import { mergeProps } from "./helpers/merge-props.mjs";
|
|
62
|
+
import { mergeRefs } from "./helpers/merge-refs.mjs";
|
|
65
63
|
import { useBreakpoint } from "./hooks/breakpoint/index.mjs";
|
|
66
64
|
import { useClickAway } from "./hooks/click-away/index.mjs";
|
|
67
65
|
import { useClient } from "./hooks/client/index.mjs";
|
|
@@ -84,4 +82,4 @@ import { useStep } from "./hooks/step/index.mjs";
|
|
|
84
82
|
import { useTimeout } from "./hooks/timeout/index.mjs";
|
|
85
83
|
import { useWindowResize } from "./hooks/window-resize/index.mjs";
|
|
86
84
|
import { useWindowSize } from "./hooks/window-size/index.mjs";
|
|
87
|
-
export { AIIcon, AccessibilityIcon, Accordion, Alert, AlertIcon, Anchor, ArteOdyssey, ArteOdysseyProvider, AtomIcon, Autocomplete, Avatar, BadIcon, Badge, BaselineStatus, BlogIcon, BoringIcon, Breadcrumb, Button, Card, CheckIcon, Checkbox, CheckboxCard, CheckboxGroup, ChevronIcon, CloseIcon, Code, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, Dialog, DifficultIcon, Direction, Drawer, DropdownMenu, EasyIcon, ExternalLinkIcon, FileField, Form, FormControl, FormIcon, GitHubIcon, GoodIcon, Heading, HistoryIcon, IconButton, InformativeIcon, InteractiveCard, InterestingIcon, LightModeIcon, LinkIcon, ListBox, ListIcon, LocationIcon, Logo, LogoIcon, MailIcon, MinusIcon, MixedColorIcon, Modal, NavigationMenuIcon, NewsIcon, NumberField, Option, Pagination, PaletteIcon, PasswordInput, PlusIcon, Popover, PortalRootProvider, PrepareIcon, Progress, PublishDateIcon, QiitaIcon, RSSIcon, Radio, RadioCard, ScrollLinked, Select, SendIcon, Separator, ShallowIcon, ShieldCheckIcon, Skeleton, SlideIcon, Slider, SparklesIcon, Spinner, Status, SubscribeIcon, Switch, Table, TableIcon, Tabs, TagIcon, TextField, Textarea, ToastProvider, Tooltip, TwitterIcon, UpdateDateIcon, ViewIcon, ViewOffIcon,
|
|
85
|
+
export { AIIcon, AccessibilityIcon, Accordion, Alert, AlertIcon, Anchor, ArteOdyssey, ArteOdysseyProvider, AtomIcon, Autocomplete, Avatar, BadIcon, Badge, BaselineStatus, BlogIcon, BoringIcon, Breadcrumb, Button, Card, CheckIcon, Checkbox, CheckboxCard, CheckboxGroup, ChevronIcon, CloseIcon, Code, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, Dialog, DifficultIcon, Direction, Drawer, DropdownMenu, EasyIcon, ExternalLinkIcon, FileField, Form, FormControl, FormIcon, GitHubIcon, GoodIcon, Heading, HistoryIcon, HorizontalWritingIcon, IconButton, InformativeIcon, InteractiveCard, InterestingIcon, LightModeIcon, LinkIcon, ListBox, ListIcon, LocationIcon, Logo, LogoIcon, MailIcon, MinusIcon, MixedColorIcon, Modal, NavigationMenuIcon, NewsIcon, NumberField, Option, Pagination, PaletteIcon, PasswordInput, PlusIcon, Popover, PortalRootProvider, PrepareIcon, Progress, PublishDateIcon, QiitaIcon, RSSIcon, Radio, RadioCard, ScrollLinked, Select, SendIcon, Separator, ShallowIcon, ShieldCheckIcon, Skeleton, SlideIcon, Slider, SparklesIcon, Spinner, Status, SubscribeIcon, Switch, Table, TableIcon, Tabs, TagIcon, TextField, Textarea, ToastProvider, Tooltip, TwitterIcon, UpdateDateIcon, VerticalWritingIcon, ViewIcon, ViewOffIcon, chain, cn, createSafeContext, mergeProps, mergeRefs, useBreakpoint, useClickAway, useClient, useClipboard, useControllableState, useDebouncedTransition, useDeferredDebounce, useDisclosure, useHash, useHover, useInView, useIntersectionObserver, useInterval, useLocalStorage, useOpenContext, usePortalRoot, useResize, useScrollDirection, useScrollLock, useSessionStorage, useStep, useTimeout, useToast, useWindowResize, useWindowSize };
|
package/dist/index.mjs
CHANGED
|
@@ -2,14 +2,15 @@ import { cn } from "./helpers/cn.mjs";
|
|
|
2
2
|
import { Spinner } from "./components/feedback/spinner/spinner.mjs";
|
|
3
3
|
import { Button } from "./components/buttons/button/button.mjs";
|
|
4
4
|
import { useDisclosure } from "./hooks/disclosure/index.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { createSafeContext } from "./helpers/create-safe-context.mjs";
|
|
6
6
|
import { useToast } from "./components/feedback/toast/context.mjs";
|
|
7
7
|
import { ArteOdyssey } from "./components/icons/arte-odyssey.mjs";
|
|
8
8
|
import { GitHubIcon } from "./components/icons/github-mark.mjs";
|
|
9
9
|
import { Logo, LogoIcon } from "./components/icons/logo.mjs";
|
|
10
|
-
import { AIIcon, AccessibilityIcon, AlertIcon, AtomIcon, BadIcon, BlogIcon, BoringIcon, CheckIcon, ChevronIcon, CloseIcon, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, DifficultIcon, EasyIcon, ExternalLinkIcon, FormIcon, GoodIcon, HistoryIcon, InformativeIcon, InterestingIcon, LightModeIcon, LinkIcon, ListIcon, LocationIcon, MailIcon, MinusIcon, MixedColorIcon, NavigationMenuIcon, NewsIcon, PaletteIcon, PlusIcon, PrepareIcon, PublishDateIcon, RSSIcon, SendIcon, ShallowIcon, ShieldCheckIcon, SlideIcon, SparklesIcon, SubscribeIcon, TableIcon, TagIcon, UpdateDateIcon, ViewIcon, ViewOffIcon } from "./components/icons/lucide.mjs";
|
|
10
|
+
import { AIIcon, AccessibilityIcon, AlertIcon, AtomIcon, BadIcon, BlogIcon, BoringIcon, CheckIcon, ChevronIcon, CloseIcon, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, DifficultIcon, EasyIcon, ExternalLinkIcon, FormIcon, GoodIcon, HistoryIcon, HorizontalWritingIcon, InformativeIcon, InterestingIcon, LightModeIcon, LinkIcon, ListIcon, LocationIcon, MailIcon, MinusIcon, MixedColorIcon, NavigationMenuIcon, NewsIcon, PaletteIcon, PlusIcon, PrepareIcon, PublishDateIcon, RSSIcon, SendIcon, ShallowIcon, ShieldCheckIcon, SlideIcon, SparklesIcon, SubscribeIcon, TableIcon, TagIcon, UpdateDateIcon, ViewIcon, ViewOffIcon } from "./components/icons/lucide.mjs";
|
|
11
11
|
import { QiitaIcon } from "./components/icons/qiita.mjs";
|
|
12
12
|
import { TwitterIcon } from "./components/icons/twitter.mjs";
|
|
13
|
+
import { VerticalWritingIcon } from "./components/icons/vertical-writing.mjs";
|
|
13
14
|
import { Alert } from "./components/feedback/alert/alert.mjs";
|
|
14
15
|
import { useTimeout } from "./hooks/timeout/index.mjs";
|
|
15
16
|
import { ToastProvider } from "./components/feedback/toast/provider.mjs";
|
|
@@ -19,6 +20,8 @@ import { useClickAway } from "./hooks/click-away/index.mjs";
|
|
|
19
20
|
import { useOpenContext } from "./components/overlays/popover/hooks.mjs";
|
|
20
21
|
import { Popover } from "./components/overlays/popover/popover.mjs";
|
|
21
22
|
import { Tooltip } from "./components/overlays/tooltip/tooltip.mjs";
|
|
23
|
+
import { chain } from "./helpers/chain.mjs";
|
|
24
|
+
import { mergeRefs } from "./helpers/merge-refs.mjs";
|
|
22
25
|
import { IconButton } from "./components/buttons/icon-button/icon-button.mjs";
|
|
23
26
|
import { Accordion } from "./components/data-display/accordion/index.mjs";
|
|
24
27
|
import { Avatar } from "./components/data-display/avatar/avatar.mjs";
|
|
@@ -27,14 +30,9 @@ import { useClient } from "./hooks/client/index.mjs";
|
|
|
27
30
|
import { BaselineStatus } from "./components/data-display/baseline-status/baseline-status.mjs";
|
|
28
31
|
import { Card } from "./components/data-display/card/card.mjs";
|
|
29
32
|
import { InteractiveCard } from "./components/data-display/card/interactive-card.mjs";
|
|
30
|
-
import { findAllColors } from "./helpers/color/find-all-colors.mjs";
|
|
31
33
|
import { Code } from "./components/data-display/code/code.mjs";
|
|
32
34
|
import { Heading } from "./components/data-display/heading/heading.mjs";
|
|
33
35
|
import { Table } from "./components/data-display/table/table.mjs";
|
|
34
|
-
import { between } from "./helpers/number/between.mjs";
|
|
35
|
-
import { toPrecision } from "./helpers/number/to-precision.mjs";
|
|
36
|
-
import { cast } from "./helpers/number/cast.mjs";
|
|
37
|
-
import { commalize } from "./helpers/number/commalize.mjs";
|
|
38
36
|
import { Progress } from "./components/feedback/progress/progress.mjs";
|
|
39
37
|
import { Skeleton } from "./components/feedback/skeleton/skeleton.mjs";
|
|
40
38
|
import { useControllableState } from "./hooks/controllable-state/index.mjs";
|
|
@@ -57,7 +55,6 @@ import { TextField } from "./components/form/text-field/text-field.mjs";
|
|
|
57
55
|
import { Textarea } from "./components/form/textarea/textarea.mjs";
|
|
58
56
|
import { ScrollLinked } from "./components/layout/scroll-linked/scroll-linked.mjs";
|
|
59
57
|
import { Separator } from "./components/layout/separator/separator.mjs";
|
|
60
|
-
import { isInternalRoute } from "./helpers/is-internal-route.mjs";
|
|
61
58
|
import { Anchor } from "./components/navigation/anchor/anchor.mjs";
|
|
62
59
|
import { Breadcrumb } from "./components/navigation/breadcrumb/breadcrumb.mjs";
|
|
63
60
|
import { Pagination } from "./components/navigation/pagination/pagination.mjs";
|
|
@@ -67,6 +64,7 @@ import { Modal } from "./components/overlays/modal/modal.mjs";
|
|
|
67
64
|
import { Drawer } from "./components/overlays/drawer/drawer.mjs";
|
|
68
65
|
import { DropdownMenu } from "./components/overlays/dropdown-menu/dropdown-menu.mjs";
|
|
69
66
|
import { ListBox } from "./components/overlays/list-box/list-box.mjs";
|
|
67
|
+
import { mergeProps } from "./helpers/merge-props.mjs";
|
|
70
68
|
import { useClipboard } from "./hooks/clipboard/index.mjs";
|
|
71
69
|
import { useDebouncedTransition } from "./hooks/debounced-transition/index.mjs";
|
|
72
70
|
import { useHash } from "./hooks/hash/index.mjs";
|
|
@@ -83,4 +81,4 @@ import { useSessionStorage } from "./hooks/session-storage/index.mjs";
|
|
|
83
81
|
import { useStep } from "./hooks/step/index.mjs";
|
|
84
82
|
import { useWindowResize } from "./hooks/window-resize/index.mjs";
|
|
85
83
|
import { useWindowSize } from "./hooks/window-size/index.mjs";
|
|
86
|
-
export { AIIcon, AccessibilityIcon, Accordion, Alert, AlertIcon, Anchor, ArteOdyssey, ArteOdysseyProvider, AtomIcon, Autocomplete, Avatar, BadIcon, Badge, BaselineStatus, BlogIcon, BoringIcon, Breadcrumb, Button, Card, CheckIcon, Checkbox, CheckboxCard, CheckboxGroup, ChevronIcon, CloseIcon, Code, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, Dialog, DifficultIcon, Drawer, DropdownMenu, EasyIcon, ExternalLinkIcon, FileField, Form, FormControl, FormIcon, GitHubIcon, GoodIcon, Heading, HistoryIcon, IconButton, InformativeIcon, InteractiveCard, InterestingIcon, LightModeIcon, LinkIcon, ListBox, ListIcon, LocationIcon, Logo, LogoIcon, MailIcon, MinusIcon, MixedColorIcon, Modal, NavigationMenuIcon, NewsIcon, NumberField, Pagination, PaletteIcon, PasswordInput, PlusIcon, Popover, PortalRootProvider, PrepareIcon, Progress, PublishDateIcon, QiitaIcon, RSSIcon, Radio, RadioCard, ScrollLinked, Select, SendIcon, Separator, ShallowIcon, ShieldCheckIcon, Skeleton, SlideIcon, Slider, SparklesIcon, Spinner, SubscribeIcon, Switch, Table, TableIcon, Tabs, TagIcon, TextField, Textarea, ToastProvider, Tooltip, TwitterIcon, UpdateDateIcon, ViewIcon, ViewOffIcon,
|
|
84
|
+
export { AIIcon, AccessibilityIcon, Accordion, Alert, AlertIcon, Anchor, ArteOdyssey, ArteOdysseyProvider, AtomIcon, Autocomplete, Avatar, BadIcon, Badge, BaselineStatus, BlogIcon, BoringIcon, Breadcrumb, Button, Card, CheckIcon, Checkbox, CheckboxCard, CheckboxGroup, ChevronIcon, CloseIcon, Code, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, Dialog, DifficultIcon, Drawer, DropdownMenu, EasyIcon, ExternalLinkIcon, FileField, Form, FormControl, FormIcon, GitHubIcon, GoodIcon, Heading, HistoryIcon, HorizontalWritingIcon, IconButton, InformativeIcon, InteractiveCard, InterestingIcon, LightModeIcon, LinkIcon, ListBox, ListIcon, LocationIcon, Logo, LogoIcon, MailIcon, MinusIcon, MixedColorIcon, Modal, NavigationMenuIcon, NewsIcon, NumberField, Pagination, PaletteIcon, PasswordInput, PlusIcon, Popover, PortalRootProvider, PrepareIcon, Progress, PublishDateIcon, QiitaIcon, RSSIcon, Radio, RadioCard, ScrollLinked, Select, SendIcon, Separator, ShallowIcon, ShieldCheckIcon, Skeleton, SlideIcon, Slider, SparklesIcon, Spinner, SubscribeIcon, Switch, Table, TableIcon, Tabs, TagIcon, TextField, Textarea, ToastProvider, Tooltip, TwitterIcon, UpdateDateIcon, VerticalWritingIcon, ViewIcon, ViewOffIcon, chain, cn, createSafeContext, mergeProps, mergeRefs, useBreakpoint, useClickAway, useClient, useClipboard, useControllableState, useDebouncedTransition, useDeferredDebounce, useDisclosure, useHash, useHover, useInView, useIntersectionObserver, useInterval, useLocalStorage, useOpenContext, usePortalRoot, useResize, useScrollDirection, useScrollLock, useSessionStorage, useStep, useTimeout, useToast, useWindowResize, useWindowSize };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/internal/clamp.ts
|
|
2
|
+
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
3
|
+
if (import.meta.vitest) describe("clamp", () => {
|
|
4
|
+
it("minとmaxの間の値の場合はそのまま返す", () => {
|
|
5
|
+
expect(clamp(5, 0, 10)).toBe(5);
|
|
6
|
+
});
|
|
7
|
+
it("minより小さい場合はminを返す", () => {
|
|
8
|
+
expect(clamp(-5, 0, 10)).toBe(0);
|
|
9
|
+
});
|
|
10
|
+
it("maxより大きい場合はmaxを返す", () => {
|
|
11
|
+
expect(clamp(15, 0, 10)).toBe(10);
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
//#endregion
|
|
15
|
+
export { clamp };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k8o/arte-odyssey",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0",
|
|
4
4
|
"description": "k8o's react ui library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"components",
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
"ui"
|
|
12
12
|
],
|
|
13
13
|
"bugs": {
|
|
14
|
-
"url": "https://github.com/k35o/
|
|
14
|
+
"url": "https://github.com/k35o/arte-odyssey/issues"
|
|
15
15
|
},
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"author": "k8o <kosakanoki@gmail.com>",
|
|
18
18
|
"repository": {
|
|
19
19
|
"type": "git",
|
|
20
|
-
"url": "git+https://github.com/k35o/
|
|
20
|
+
"url": "git+https://github.com/k35o/arte-odyssey.git"
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"dist/**",
|
|
@@ -69,8 +69,8 @@
|
|
|
69
69
|
"@vitest/coverage-v8": "4.1.5",
|
|
70
70
|
"@vitest/ui": "4.1.5",
|
|
71
71
|
"postcss": "8.5.13",
|
|
72
|
-
"react": "19.2.
|
|
73
|
-
"react-dom": "19.2.
|
|
72
|
+
"react": "19.2.6",
|
|
73
|
+
"react-dom": "19.2.6",
|
|
74
74
|
"storybook": "10.3.6",
|
|
75
75
|
"storybook-addon-mock-date": "2.0.0",
|
|
76
76
|
"tailwindcss": "4.2.4",
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
//#region src/helpers/is-internal-route.ts
|
|
2
|
-
const isInternalRoute = (href) => !href.startsWith("http");
|
|
3
|
-
if (import.meta.vitest) {
|
|
4
|
-
it("httpから始まるhrefはexternalなものとして判定する", () => {
|
|
5
|
-
expect(isInternalRoute("https://k8o.me/dummy")).toBe(false);
|
|
6
|
-
});
|
|
7
|
-
it("httpから始まらないhrefはexternalなものとして判定する", () => {
|
|
8
|
-
expect(isInternalRoute("/dummy")).toBe(true);
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
//#endregion
|
|
12
|
-
export { isInternalRoute };
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
//#region src/helpers/number/between.ts
|
|
2
|
-
const between = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
3
|
-
if (import.meta.vitest) describe("between", () => {
|
|
4
|
-
it("minとmaxの間の値の場合はそのまま返す", () => {
|
|
5
|
-
expect(between(5, 0, 10)).toBe(5);
|
|
6
|
-
});
|
|
7
|
-
it("minより小さい場合はminを返す", () => {
|
|
8
|
-
expect(between(-5, 0, 10)).toBe(0);
|
|
9
|
-
});
|
|
10
|
-
it("maxより大きい場合はmaxを返す", () => {
|
|
11
|
-
expect(between(15, 0, 10)).toBe(10);
|
|
12
|
-
});
|
|
13
|
-
});
|
|
14
|
-
//#endregion
|
|
15
|
-
export { between };
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
//#region src/helpers/number/commalize.ts
|
|
2
|
-
const commalize = (num) => {
|
|
3
|
-
return Math.round(num).toString().replaceAll(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
4
|
-
};
|
|
5
|
-
if (import.meta.vitest) {
|
|
6
|
-
it("3桁未満の場合はそのまま返す", () => {
|
|
7
|
-
expect(commalize(100)).toBe("100");
|
|
8
|
-
});
|
|
9
|
-
it("4桁の場合はカンマ区切りにする", () => {
|
|
10
|
-
expect(commalize(1e3)).toBe("1,000");
|
|
11
|
-
});
|
|
12
|
-
it("3桁毎にカンマ区切りにする", () => {
|
|
13
|
-
expect(commalize(1e6)).toBe("1,000,000");
|
|
14
|
-
});
|
|
15
|
-
it("少数の場合は四捨五入して整数にする", () => {
|
|
16
|
-
expect(commalize(1000.5)).toBe("1,001");
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
//#endregion
|
|
20
|
-
export { commalize };
|
package/dist/helpers/uuid-v4.mjs
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
//#region src/helpers/uuid-v4.ts
|
|
2
|
-
const HEX_BASE = 16;
|
|
3
|
-
const uuidV4 = () => {
|
|
4
|
-
if (typeof window !== "undefined" && isSecureContext) return crypto.randomUUID();
|
|
5
|
-
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replaceAll(/[xy]/g, (c) => {
|
|
6
|
-
const randHex = Math.floor(Math.random() * HEX_BASE);
|
|
7
|
-
if (c === "y") return (randHex & 3 | 8).toString(HEX_BASE);
|
|
8
|
-
return randHex.toString(HEX_BASE);
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
if (import.meta.vitest) {
|
|
12
|
-
const testRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
vi.unstubAllGlobals();
|
|
15
|
-
});
|
|
16
|
-
it("安全なコンテキストではrandUUIDからuuidv4を返す", () => {
|
|
17
|
-
vi.stubGlobal("isSecureContext", true);
|
|
18
|
-
const result = uuidV4();
|
|
19
|
-
expect(result).toMatch(testRegex);
|
|
20
|
-
});
|
|
21
|
-
it("安全なコンテキスト外では自作のuuidv4を返す", () => {
|
|
22
|
-
vi.stubGlobal("isSecureContext", false);
|
|
23
|
-
const result = uuidV4();
|
|
24
|
-
expect(result).toMatch(testRegex);
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
//#endregion
|
|
28
|
-
export { uuidV4 };
|