@m1kapp/kit 0.0.24 → 0.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +221 -2
- package/bin/claim.mjs +77 -0
- package/bin/m1kkit.mjs +10 -0
- package/bin/skills/m1kapp-init.md +108 -92
- package/bin/skills/m1kapp-stats.md +70 -0
- package/bin/skills.mjs +4 -0
- package/bin/track.mjs +95 -0
- package/dist/index.d.mts +636 -5
- package/dist/index.d.ts +636 -5
- package/dist/index.js +4 -4
- package/dist/index.mjs +4 -4
- package/dist/meta.json +10 -10
- package/dist/pwa.js +2 -2
- package/dist/pwa.mjs +1 -1
- package/dist/styles.css +1 -1
- package/dist/utils.d.mts +17 -1
- package/dist/utils.d.ts +17 -1
- package/dist/utils.js +1 -1
- package/dist/utils.mjs +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React$1 from 'react';
|
|
3
|
-
import React__default, { ReactNode, CSSProperties, RefObject } from 'react';
|
|
3
|
+
import React__default, { ReactNode, CSSProperties, RefObject, SyntheticEvent } from 'react';
|
|
4
4
|
import { MetadataRoute, Viewport } from 'next';
|
|
5
5
|
import { ClassValue } from 'clsx';
|
|
6
6
|
|
|
@@ -45,13 +45,19 @@ interface AppShellProps {
|
|
|
45
45
|
maxWidth?: number;
|
|
46
46
|
/** Max height of the shell. Default: 932px (iPhone 15 Pro Max) */
|
|
47
47
|
maxHeight?: number;
|
|
48
|
+
/**
|
|
49
|
+
* Accent color (any CSS color) propagated to kit components as `--kit-accent`.
|
|
50
|
+
* Lets you re-skin the whole shell — Switch, SegmentedControl, ChatBubble,
|
|
51
|
+
* ActionCard, ListRow… — in one place. e.g. accent="#e2603f"
|
|
52
|
+
*/
|
|
53
|
+
accent?: string;
|
|
48
54
|
style?: CSSProperties;
|
|
49
55
|
}
|
|
50
56
|
/**
|
|
51
57
|
* Mobile app-like container with rounded corners, shadow, and ring.
|
|
52
58
|
* Centers content and constrains width for a phone-like viewport.
|
|
53
59
|
*/
|
|
54
|
-
declare function AppShell({ children, className, maxWidth, maxHeight, style, }: AppShellProps): react_jsx_runtime.JSX.Element;
|
|
60
|
+
declare function AppShell({ children, className, maxWidth, maxHeight, accent, style, }: AppShellProps): react_jsx_runtime.JSX.Element;
|
|
55
61
|
interface AppShellHeaderProps {
|
|
56
62
|
children: ReactNode;
|
|
57
63
|
className?: string;
|
|
@@ -108,6 +114,12 @@ interface TabProps {
|
|
|
108
114
|
}
|
|
109
115
|
/**
|
|
110
116
|
* Individual tab button for the TabBar.
|
|
117
|
+
*
|
|
118
|
+
* The active state is conveyed two ways so it works for BOTH `currentColor`
|
|
119
|
+
* SVG icons and full-color emoji icons (emoji ignore `color`): the inactive
|
|
120
|
+
* tab is dimmed (opacity + slight desaturation) with a muted label, while the
|
|
121
|
+
* active tab is full-strength with its label tinted `activeColor`. The icon is
|
|
122
|
+
* wrapped at a consistent size so mixed emoji/SVG icons line up.
|
|
111
123
|
*/
|
|
112
124
|
declare function Tab({ active, onClick, icon, label, activeColor }: TabProps): react_jsx_runtime.JSX.Element;
|
|
113
125
|
|
|
@@ -202,6 +214,20 @@ interface WatermarkProps {
|
|
|
202
214
|
* Default: false (badge is shown)
|
|
203
215
|
*/
|
|
204
216
|
hidePoweredBy?: boolean;
|
|
217
|
+
/**
|
|
218
|
+
* m1k.app visitor-tracker slug, forwarded to the embedded PoweredByKit badge.
|
|
219
|
+
* Falls back to `NEXT_PUBLIC_M1K_SLUG`. No slug → no tracking (off by default).
|
|
220
|
+
*/
|
|
221
|
+
trackSlug?: string;
|
|
222
|
+
/** Set false to disable the visitor beacon even when a slug is present */
|
|
223
|
+
track?: boolean;
|
|
224
|
+
/** Mark the site as claimed (인증됨). When tracking but not claimed, a "미인증" marker shows. */
|
|
225
|
+
claimed?: boolean;
|
|
226
|
+
/** Visitor counts for the footer ({ today, total }). Omit to auto-fetch from m1k.app. */
|
|
227
|
+
counts?: {
|
|
228
|
+
today?: number;
|
|
229
|
+
total?: number;
|
|
230
|
+
};
|
|
205
231
|
}
|
|
206
232
|
/**
|
|
207
233
|
* Full-screen colored background with repeating animated text watermark pattern.
|
|
@@ -209,7 +235,7 @@ interface WatermarkProps {
|
|
|
209
235
|
* Renders as a single SVG element with a <pattern> — zero extra DOM nodes per tile.
|
|
210
236
|
* Sponsor tiles inside the pattern are clickable and support hover effects.
|
|
211
237
|
*/
|
|
212
|
-
declare function Watermark({ children, color, text, maxWidth, sponsor, speed, hidePoweredBy, }: WatermarkProps): react_jsx_runtime.JSX.Element;
|
|
238
|
+
declare function Watermark({ children, color, text, maxWidth, sponsor, speed, hidePoweredBy, trackSlug, track, claimed, counts, }: WatermarkProps): react_jsx_runtime.JSX.Element;
|
|
213
239
|
|
|
214
240
|
declare const colors: {
|
|
215
241
|
readonly blue: "#3b82f6";
|
|
@@ -670,6 +696,31 @@ interface PoweredByKitProps {
|
|
|
670
696
|
version?: string;
|
|
671
697
|
/** "default" for inside AppShell, "overlay" for on top of Watermark background */
|
|
672
698
|
variant?: "default" | "overlay";
|
|
699
|
+
/**
|
|
700
|
+
* m1k.app visitor-tracker slug. When set (explicitly or via the
|
|
701
|
+
* `NEXT_PUBLIC_M1K_SLUG` env var) a tiny hidden beacon counts each page view.
|
|
702
|
+
* No slug → no tracking (off by default). Register one with `npx m1kkit track`.
|
|
703
|
+
*/
|
|
704
|
+
slug?: string;
|
|
705
|
+
/** Tracker host. Default: "m1k.app" */
|
|
706
|
+
trackerHost?: string;
|
|
707
|
+
/** Set false to disable the visitor beacon even when a slug is present */
|
|
708
|
+
track?: boolean;
|
|
709
|
+
/**
|
|
710
|
+
* Whether the registered site has been claimed (귀속/인증) to an m1k.app account.
|
|
711
|
+
* When tracking is active but this is false, the badge shows a "미인증" marker.
|
|
712
|
+
* Set true after running `npx m1kkit claim`. Defaults to false.
|
|
713
|
+
*/
|
|
714
|
+
claimed?: boolean;
|
|
715
|
+
/**
|
|
716
|
+
* Visitor counts to display ({ today, total }). If omitted, fetched from
|
|
717
|
+
* `https://<trackerHost>/api/sites/<slug>` (needs CORS). Pass explicitly to
|
|
718
|
+
* avoid the fetch (SSR, custom source, or cross-origin without CORS).
|
|
719
|
+
*/
|
|
720
|
+
counts?: {
|
|
721
|
+
today?: number;
|
|
722
|
+
total?: number;
|
|
723
|
+
};
|
|
673
724
|
className?: string;
|
|
674
725
|
}
|
|
675
726
|
/**
|
|
@@ -679,7 +730,571 @@ interface PoweredByKitProps {
|
|
|
679
730
|
* Fetches /kit-stats.json (generated by `m1kkit stats`) on first open
|
|
680
731
|
* to show real code analysis results.
|
|
681
732
|
*/
|
|
682
|
-
declare function PoweredByKit({ statsUrl, version, variant, className }: PoweredByKitProps): react_jsx_runtime.JSX.Element;
|
|
733
|
+
declare function PoweredByKit({ statsUrl, version, variant, slug, trackerHost, track, claimed, counts, className }: PoweredByKitProps): react_jsx_runtime.JSX.Element;
|
|
734
|
+
|
|
735
|
+
interface SwitchProps {
|
|
736
|
+
/** Whether the switch is on */
|
|
737
|
+
checked: boolean;
|
|
738
|
+
/** Called with the next value when toggled */
|
|
739
|
+
onChange: (next: boolean) => void;
|
|
740
|
+
disabled?: boolean;
|
|
741
|
+
/** On-state track color (any CSS color). Defaults to `var(--kit-accent)`. */
|
|
742
|
+
accent?: string;
|
|
743
|
+
/** Accessible label */
|
|
744
|
+
"aria-label"?: string;
|
|
745
|
+
className?: string;
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* On/off toggle switch. Pill track + sliding knob, adapts to dark mode.
|
|
749
|
+
* On-state color follows `--kit-accent` (set via `<AppShell accent>`) or the `accent` prop.
|
|
750
|
+
*
|
|
751
|
+
* @example
|
|
752
|
+
* <Switch checked={on} onChange={setOn} aria-label="알림" />
|
|
753
|
+
* <Switch checked={on} onChange={setOn} accent="#e2603f" />
|
|
754
|
+
*/
|
|
755
|
+
declare function Switch({ checked, onChange, disabled, accent, className, ...rest }: SwitchProps): react_jsx_runtime.JSX.Element;
|
|
756
|
+
|
|
757
|
+
interface FieldProps {
|
|
758
|
+
/** Label shown above (or beside, when `inline`) the input */
|
|
759
|
+
label: ReactNode;
|
|
760
|
+
value: string;
|
|
761
|
+
/** Omit to render a read-only display row */
|
|
762
|
+
onChange?: (value: string) => void;
|
|
763
|
+
placeholder?: string;
|
|
764
|
+
/** input type (text, email, tel…). Ignored when `multiline`. */
|
|
765
|
+
type?: string;
|
|
766
|
+
/** Render a textarea instead of an input */
|
|
767
|
+
multiline?: boolean;
|
|
768
|
+
rows?: number;
|
|
769
|
+
readOnly?: boolean;
|
|
770
|
+
disabled?: boolean;
|
|
771
|
+
/** Helper text under the field */
|
|
772
|
+
hint?: ReactNode;
|
|
773
|
+
/** Label beside the input on one line (settings-row style) instead of stacked */
|
|
774
|
+
inline?: boolean;
|
|
775
|
+
className?: string;
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Labeled input row for forms. Stacked by default, or `inline` for a
|
|
779
|
+
* settings-style "label … value" row. Supports textarea via `multiline`.
|
|
780
|
+
*
|
|
781
|
+
* @example
|
|
782
|
+
* <Field label="이름" value={name} onChange={setName} placeholder="이름" />
|
|
783
|
+
* <Field label="메모" value={memo} onChange={setMemo} multiline rows={3} />
|
|
784
|
+
* <Field label="이메일" value={email} inline readOnly />
|
|
785
|
+
*/
|
|
786
|
+
declare function Field({ label, value, onChange, placeholder, type, multiline, rows, readOnly, disabled, hint, inline, className, }: FieldProps): react_jsx_runtime.JSX.Element;
|
|
787
|
+
|
|
788
|
+
interface SegmentOption<T extends string> {
|
|
789
|
+
value: T;
|
|
790
|
+
label: ReactNode;
|
|
791
|
+
}
|
|
792
|
+
interface SegmentedControlProps<T extends string> {
|
|
793
|
+
options: SegmentOption<T>[];
|
|
794
|
+
value: T;
|
|
795
|
+
onChange: (value: T) => void;
|
|
796
|
+
/** Active-segment label color (any CSS color). Defaults to `var(--kit-accent)`. */
|
|
797
|
+
accent?: string;
|
|
798
|
+
className?: string;
|
|
799
|
+
}
|
|
800
|
+
/**
|
|
801
|
+
* Inline segmented toggle (e.g. 오늘 / 이번 주). The active segment lifts onto a
|
|
802
|
+
* card; its label takes the accent color. For global bottom nav use `TabBar` instead.
|
|
803
|
+
*
|
|
804
|
+
* @example
|
|
805
|
+
* <SegmentedControl
|
|
806
|
+
* value={view}
|
|
807
|
+
* onChange={setView}
|
|
808
|
+
* options={[{ value: "today", label: "오늘" }, { value: "week", label: "이번 주" }]}
|
|
809
|
+
* />
|
|
810
|
+
*/
|
|
811
|
+
declare function SegmentedControl<T extends string>({ options, value, onChange, accent, className, }: SegmentedControlProps<T>): react_jsx_runtime.JSX.Element;
|
|
812
|
+
|
|
813
|
+
type ChatRole = "user" | "assistant";
|
|
814
|
+
interface ChatBubbleProps {
|
|
815
|
+
role: ChatRole;
|
|
816
|
+
children: ReactNode;
|
|
817
|
+
/** User-bubble background (any CSS color). Defaults to `var(--kit-accent)`. */
|
|
818
|
+
accent?: string;
|
|
819
|
+
className?: string;
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Chat message bubble. User messages align right with the accent color and a
|
|
823
|
+
* tail on the bottom-right; assistant messages align left on a neutral surface.
|
|
824
|
+
* Preserves newlines (`whitespace-pre-wrap`).
|
|
825
|
+
*
|
|
826
|
+
* @example
|
|
827
|
+
* <ChatBubble role="user">오늘 3시 회의 잡아줘</ChatBubble>
|
|
828
|
+
* <ChatBubble role="assistant">네, 잡아드릴게요.</ChatBubble>
|
|
829
|
+
*/
|
|
830
|
+
declare function ChatBubble({ role, children, accent, className }: ChatBubbleProps): react_jsx_runtime.JSX.Element;
|
|
831
|
+
interface TypingIndicatorProps {
|
|
832
|
+
className?: string;
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* Three-dot "typing…" indicator on an assistant-style surface.
|
|
836
|
+
*
|
|
837
|
+
* @example
|
|
838
|
+
* {pending && <TypingIndicator />}
|
|
839
|
+
*/
|
|
840
|
+
declare function TypingIndicator({ className }: TypingIndicatorProps): react_jsx_runtime.JSX.Element;
|
|
841
|
+
interface ChatMessage {
|
|
842
|
+
id?: string | number;
|
|
843
|
+
role: ChatRole;
|
|
844
|
+
content: ReactNode;
|
|
845
|
+
/** Epoch ms — required for day dividers */
|
|
846
|
+
timestamp?: number;
|
|
847
|
+
}
|
|
848
|
+
interface MessageListProps {
|
|
849
|
+
messages: ChatMessage[];
|
|
850
|
+
/** Insert a date divider when the day changes between messages */
|
|
851
|
+
dayDivider?: boolean;
|
|
852
|
+
/** User-bubble accent (forwarded to each ChatBubble) */
|
|
853
|
+
accent?: string;
|
|
854
|
+
/** Format a divider label from a timestamp. Defaults to a Korean date label. */
|
|
855
|
+
formatDay?: (ts: number) => string;
|
|
856
|
+
/** Rendered after the last message — e.g. a <TypingIndicator /> */
|
|
857
|
+
children?: ReactNode;
|
|
858
|
+
className?: string;
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Renders a vertical list of chat messages as bubbles, optionally inserting a
|
|
862
|
+
* date divider when the calendar day changes (requires `timestamp` on messages).
|
|
863
|
+
*
|
|
864
|
+
* @example
|
|
865
|
+
* <MessageList messages={msgs} dayDivider>
|
|
866
|
+
* {pending && <TypingIndicator />}
|
|
867
|
+
* </MessageList>
|
|
868
|
+
*/
|
|
869
|
+
declare function MessageList({ messages, dayDivider, accent, formatDay, children, className, }: MessageListProps): react_jsx_runtime.JSX.Element;
|
|
870
|
+
|
|
871
|
+
type ActionCardState = "pending" | "loading" | "done" | "cancelled";
|
|
872
|
+
interface ActionCardLabels {
|
|
873
|
+
/** Title shown while pending (defaults to `title`) */
|
|
874
|
+
pending?: string;
|
|
875
|
+
loading?: string;
|
|
876
|
+
done?: string;
|
|
877
|
+
cancelled?: string;
|
|
878
|
+
confirm?: string;
|
|
879
|
+
cancel?: string;
|
|
880
|
+
}
|
|
881
|
+
interface ActionCardProps {
|
|
882
|
+
/** Title shown in the pending state */
|
|
883
|
+
title?: string;
|
|
884
|
+
/** Lines of content (e.g. a proposed plan) */
|
|
885
|
+
items?: ReactNode[];
|
|
886
|
+
/** Free-form body rendered below items */
|
|
887
|
+
children?: ReactNode;
|
|
888
|
+
state?: ActionCardState;
|
|
889
|
+
onConfirm?: () => void;
|
|
890
|
+
onCancel?: () => void;
|
|
891
|
+
/** Accent (any CSS color) for the pending border/title/confirm button. Defaults to `var(--kit-accent)`. */
|
|
892
|
+
accent?: string;
|
|
893
|
+
/** Override default Korean status labels */
|
|
894
|
+
labels?: ActionCardLabels;
|
|
895
|
+
className?: string;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Inline confirm card for the "propose → confirm → execute" pattern (LLM tool
|
|
899
|
+
* calls, etc.). Unlike `Dialog` it sits inside the message flow. Its color and
|
|
900
|
+
* affordances change with `state`; action buttons show only while `pending`.
|
|
901
|
+
*
|
|
902
|
+
* @example
|
|
903
|
+
* <ActionCard
|
|
904
|
+
* title="이렇게 기록해둘까요?"
|
|
905
|
+
* state={state}
|
|
906
|
+
* items={["🗓 6/4 15:00 디자인리뷰"]}
|
|
907
|
+
* onConfirm={commit}
|
|
908
|
+
* onCancel={cancel}
|
|
909
|
+
* />
|
|
910
|
+
*/
|
|
911
|
+
declare function ActionCard({ title, items, children, state, onConfirm, onCancel, accent, labels, className, }: ActionCardProps): react_jsx_runtime.JSX.Element;
|
|
912
|
+
|
|
913
|
+
interface ListRowProps {
|
|
914
|
+
/** Left color bar + active highlight tint. Defaults to `var(--kit-accent)`. */
|
|
915
|
+
accent?: string;
|
|
916
|
+
/** Leading column, e.g. a time like "14:00" */
|
|
917
|
+
lead?: ReactNode;
|
|
918
|
+
/** Secondary leading line under `lead`, e.g. an end time */
|
|
919
|
+
leadSub?: ReactNode;
|
|
920
|
+
title: ReactNode;
|
|
921
|
+
/** Secondary line under the title */
|
|
922
|
+
sub?: ReactNode;
|
|
923
|
+
/** Trailing content, e.g. "● 지금" or a count badge */
|
|
924
|
+
trailing?: ReactNode;
|
|
925
|
+
/** Highlight as the current/active row */
|
|
926
|
+
active?: boolean;
|
|
927
|
+
/**
|
|
928
|
+
* Scale the row height in units (1 = base height, clamped 46–130px). Useful
|
|
929
|
+
* for any timeline where rows have different magnitudes.
|
|
930
|
+
* For a schedule, pass `durationMinutes / 30`.
|
|
931
|
+
*/
|
|
932
|
+
heightScale?: number;
|
|
933
|
+
onClick?: () => void;
|
|
934
|
+
className?: string;
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* Timeline / list row: left color bar, a leading column (time), a title with an
|
|
938
|
+
* optional subtitle, and trailing content. Height can scale via `heightScale` —
|
|
939
|
+
* handy for schedules, to-dos, Gantt-style timelines, and time blocks.
|
|
940
|
+
*
|
|
941
|
+
* @example
|
|
942
|
+
* <ListRow accent="#7fc06a" lead="14:00" title="회의" sub="👥 김상훈" heightScale={2} onClick={open} />
|
|
943
|
+
* <ListRow lead="09:00" title="스탠드업" trailing="● 지금" active />
|
|
944
|
+
*/
|
|
945
|
+
declare function ListRow({ accent, lead, leadSub, title, sub, trailing, active, heightScale, onClick, className, }: ListRowProps): react_jsx_runtime.JSX.Element;
|
|
946
|
+
|
|
947
|
+
interface LinkifiedTextProps {
|
|
948
|
+
children: string;
|
|
949
|
+
/** Link color (any CSS color). Defaults to `var(--kit-accent)`. */
|
|
950
|
+
accent?: string;
|
|
951
|
+
/** Also linkify bare domains with a path, e.g. `meet.google.com/abc`. Default: true */
|
|
952
|
+
linkifyBareDomains?: boolean;
|
|
953
|
+
className?: string;
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* Renders plain text with URLs auto-linked. Preserves newlines
|
|
957
|
+
* (`whitespace-pre-wrap`). Link color follows `--kit-accent` or the `accent` prop.
|
|
958
|
+
*
|
|
959
|
+
* @example
|
|
960
|
+
* <LinkifiedText>회의록: https://docs.google.com/… 그리고 meet.google.com/abc-def</LinkifiedText>
|
|
961
|
+
*/
|
|
962
|
+
declare function LinkifiedText({ children, accent, linkifyBareDomains, className, }: LinkifiedTextProps): react_jsx_runtime.JSX.Element;
|
|
963
|
+
|
|
964
|
+
interface Step {
|
|
965
|
+
label: ReactNode;
|
|
966
|
+
/** Optional icon/emoji shown in the badge while incomplete */
|
|
967
|
+
icon?: ReactNode;
|
|
968
|
+
}
|
|
969
|
+
interface StepperProps {
|
|
970
|
+
steps: Step[];
|
|
971
|
+
/** Active step index (0-based) */
|
|
972
|
+
current: number;
|
|
973
|
+
/** Last completed index (default: current - 1). Steps ≤ this show a check. */
|
|
974
|
+
completedThrough?: number;
|
|
975
|
+
/** Makes steps up to `current` clickable */
|
|
976
|
+
onStepClick?: (index: number) => void;
|
|
977
|
+
/** Active/complete color (any CSS color). Defaults to `var(--kit-accent)`. */
|
|
978
|
+
accent?: string;
|
|
979
|
+
className?: string;
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Horizontal multi-step progress indicator with connectors. Steps before the
|
|
983
|
+
* cursor show a check, the current step is highlighted, the rest are muted.
|
|
984
|
+
* Great for wizards, multi-phase flows, and onboarding.
|
|
985
|
+
*
|
|
986
|
+
* @example
|
|
987
|
+
* <Stepper current={phase} onStepClick={setPhase} steps={[
|
|
988
|
+
* { label: "분석", icon: "📝" },
|
|
989
|
+
* { label: "준비", icon: "📸" },
|
|
990
|
+
* { label: "생성", icon: "✨" },
|
|
991
|
+
* ]} />
|
|
992
|
+
*/
|
|
993
|
+
declare function Stepper({ steps, current, completedThrough, onStepClick, accent, className, }: StepperProps): react_jsx_runtime.JSX.Element;
|
|
994
|
+
|
|
995
|
+
interface CollapsibleProps {
|
|
996
|
+
title: ReactNode;
|
|
997
|
+
/** Subtitle shown only while collapsed */
|
|
998
|
+
subtitle?: ReactNode;
|
|
999
|
+
/** Small badge text shown only while collapsed */
|
|
1000
|
+
badge?: ReactNode;
|
|
1001
|
+
/** Leading marker — a step number, letter, or icon */
|
|
1002
|
+
leading?: ReactNode;
|
|
1003
|
+
open: boolean;
|
|
1004
|
+
onToggle: () => void;
|
|
1005
|
+
/** Show the leading marker as completed (accent + check) */
|
|
1006
|
+
completed?: boolean;
|
|
1007
|
+
/** Small "선택"-style optional tag next to the title */
|
|
1008
|
+
optionalTag?: ReactNode;
|
|
1009
|
+
/** Accent (any CSS color) for expanded ring / completed marker. Defaults to `var(--kit-accent)`. */
|
|
1010
|
+
accent?: string;
|
|
1011
|
+
children: ReactNode;
|
|
1012
|
+
className?: string;
|
|
1013
|
+
}
|
|
1014
|
+
/**
|
|
1015
|
+
* Collapsible card with a header (leading marker, title, optional subtitle/badge)
|
|
1016
|
+
* and a body that shows when `open`. State-aware styling for expanded/completed.
|
|
1017
|
+
* Good for step lists, accordions, and disclosure sections.
|
|
1018
|
+
*
|
|
1019
|
+
* @example
|
|
1020
|
+
* <Collapsible leading={1} title="페르소나 분석" subtitle="스타일 파악"
|
|
1021
|
+
* open={open === 1} onToggle={() => setOpen(open === 1 ? null : 1)} completed>
|
|
1022
|
+
* <p>…</p>
|
|
1023
|
+
* </Collapsible>
|
|
1024
|
+
*/
|
|
1025
|
+
declare function Collapsible({ title, subtitle, badge, leading, open, onToggle, completed, optionalTag, accent, children, className, }: CollapsibleProps): react_jsx_runtime.JSX.Element;
|
|
1026
|
+
|
|
1027
|
+
/**
|
|
1028
|
+
* Clipboard copy + feedback. `copied` is `true` (or the passed `key`) for
|
|
1029
|
+
* `timeout` ms after a copy, so one hook can drive many copy targets.
|
|
1030
|
+
*
|
|
1031
|
+
* @example
|
|
1032
|
+
* const { copied, copy } = useCopy();
|
|
1033
|
+
* copy(text); // copied === true
|
|
1034
|
+
* copy(text, "row-3"); // copied === "row-3" (multiple targets)
|
|
1035
|
+
*/
|
|
1036
|
+
declare function useCopy(timeout?: number): {
|
|
1037
|
+
copied: string | boolean | null;
|
|
1038
|
+
copy: (text: string, key?: string) => void;
|
|
1039
|
+
};
|
|
1040
|
+
interface CopyButtonProps {
|
|
1041
|
+
/** Text to copy */
|
|
1042
|
+
text: string;
|
|
1043
|
+
/** Button label (default: "복사") */
|
|
1044
|
+
children?: ReactNode;
|
|
1045
|
+
/** Label shown briefly after copying (default: "복사됨!") */
|
|
1046
|
+
copiedLabel?: ReactNode;
|
|
1047
|
+
/** Accent (any CSS color) for the copied state. Defaults to `var(--kit-accent)`. */
|
|
1048
|
+
accent?: string;
|
|
1049
|
+
timeout?: number;
|
|
1050
|
+
className?: string;
|
|
1051
|
+
}
|
|
1052
|
+
/**
|
|
1053
|
+
* Button that copies `text` to the clipboard and flips its label to a confirmation.
|
|
1054
|
+
*
|
|
1055
|
+
* @example
|
|
1056
|
+
* <CopyButton text="npm i @m1kapp/kit">설치 명령 복사</CopyButton>
|
|
1057
|
+
*/
|
|
1058
|
+
declare function CopyButton({ text, children, copiedLabel, accent, timeout, className, }: CopyButtonProps): react_jsx_runtime.JSX.Element;
|
|
1059
|
+
|
|
1060
|
+
type ImgStatus = "loading" | "loaded" | "failed";
|
|
1061
|
+
/**
|
|
1062
|
+
* Tries an ordered list of image URLs, falling back to the next on error or
|
|
1063
|
+
* when an image loads too small/broken. Handles already-cached images.
|
|
1064
|
+
* Returns props to spread onto an `<img>`.
|
|
1065
|
+
*
|
|
1066
|
+
* @example
|
|
1067
|
+
* const { status, url, refCallback, handleLoad, handleError } = useImageLoader([a, b]);
|
|
1068
|
+
* if (status === "failed") return <Fallback />;
|
|
1069
|
+
* return <img ref={refCallback} src={url!} onLoad={handleLoad} onError={handleError} />;
|
|
1070
|
+
*/
|
|
1071
|
+
declare function useImageLoader(urls: string[]): {
|
|
1072
|
+
status: ImgStatus;
|
|
1073
|
+
url: string | null;
|
|
1074
|
+
refCallback: (el: HTMLImageElement | null) => void;
|
|
1075
|
+
handleLoad: (e: SyntheticEvent<HTMLImageElement>) => void;
|
|
1076
|
+
handleError: () => void;
|
|
1077
|
+
};
|
|
1078
|
+
interface ImgProps {
|
|
1079
|
+
/** Single source, or use `candidates` for ordered fallback */
|
|
1080
|
+
src?: string | null;
|
|
1081
|
+
/** Ordered candidate URLs; first one that loads wins */
|
|
1082
|
+
candidates?: string[];
|
|
1083
|
+
/** Shown when all sources fail (or none given) */
|
|
1084
|
+
fallback?: ReactNode;
|
|
1085
|
+
alt?: string;
|
|
1086
|
+
className?: string;
|
|
1087
|
+
style?: CSSProperties;
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
1090
|
+
* `<img>` with multi-URL fallback and a render fallback when every source fails.
|
|
1091
|
+
*
|
|
1092
|
+
* @example
|
|
1093
|
+
* <Img candidates={[avatarUrl, gravatar]} fallback={<Avatar fallback="MH" />} alt="" className="h-10 w-10 rounded-full" />
|
|
1094
|
+
*/
|
|
1095
|
+
declare function Img({ src, candidates, fallback, alt, className, style }: ImgProps): react_jsx_runtime.JSX.Element;
|
|
1096
|
+
|
|
1097
|
+
interface SelectOption<T extends string | number> {
|
|
1098
|
+
value: T;
|
|
1099
|
+
label: ReactNode;
|
|
1100
|
+
/** Optional count shown on the right (e.g. number of matches) */
|
|
1101
|
+
count?: number;
|
|
1102
|
+
/** Disable selection (e.g. count === 0) */
|
|
1103
|
+
disabled?: boolean;
|
|
1104
|
+
}
|
|
1105
|
+
interface SelectProps<T extends string | number> {
|
|
1106
|
+
options: SelectOption<T>[];
|
|
1107
|
+
value: T | null;
|
|
1108
|
+
onChange: (value: T | null) => void;
|
|
1109
|
+
/** Trigger text when nothing is selected (default: "전체") */
|
|
1110
|
+
placeholder?: ReactNode;
|
|
1111
|
+
/** Show a top "clear" row that sets value to null (default: true) */
|
|
1112
|
+
allowClear?: boolean;
|
|
1113
|
+
/** Label for the clear row (default: "전체") */
|
|
1114
|
+
clearLabel?: ReactNode;
|
|
1115
|
+
/** Accent (any CSS color) for the selected trigger. Defaults to `var(--kit-accent)`. */
|
|
1116
|
+
accent?: string;
|
|
1117
|
+
className?: string;
|
|
1118
|
+
}
|
|
1119
|
+
/**
|
|
1120
|
+
* Styled dropdown select: a trigger button + an anchored options list with
|
|
1121
|
+
* optional count badges and disabled options. Closes on outside click / Escape.
|
|
1122
|
+
*
|
|
1123
|
+
* @example
|
|
1124
|
+
* <Select value={cat} onChange={setCat} placeholder="카테고리"
|
|
1125
|
+
* options={[{ value: "a", label: "초급", count: 12 }, { value: "b", label: "고급", count: 0, disabled: true }]} />
|
|
1126
|
+
*/
|
|
1127
|
+
declare function Select<T extends string | number>({ options, value, onChange, placeholder, allowClear, clearLabel, accent, className, }: SelectProps<T>): react_jsx_runtime.JSX.Element;
|
|
1128
|
+
|
|
1129
|
+
interface ColorPickerProps {
|
|
1130
|
+
/** Selected color as a hex string (e.g. "#e2603f") */
|
|
1131
|
+
value: string;
|
|
1132
|
+
onChange: (hex: string) => void;
|
|
1133
|
+
/** Preset swatches. Defaults to the kit `colors` palette. */
|
|
1134
|
+
palette?: string[];
|
|
1135
|
+
/** Allow picking an arbitrary color via the native color input (default: true) */
|
|
1136
|
+
allowCustom?: boolean;
|
|
1137
|
+
className?: string;
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Color swatch picker — preset circles plus an optional custom color input.
|
|
1141
|
+
* The selected swatch gets a ring. Any hex is allowed via the custom input.
|
|
1142
|
+
*
|
|
1143
|
+
* @example
|
|
1144
|
+
* <ColorPicker value={color} onChange={setColor} />
|
|
1145
|
+
* <ColorPicker value={color} onChange={setColor} palette={["#e2603f", "#3b82f6"]} />
|
|
1146
|
+
*/
|
|
1147
|
+
declare function ColorPicker({ value, onChange, palette, allowCustom, className, }: ColorPickerProps): react_jsx_runtime.JSX.Element;
|
|
1148
|
+
|
|
1149
|
+
interface CodeBlockProps {
|
|
1150
|
+
code: string;
|
|
1151
|
+
/** Small uppercase label above the code (e.g. "bash", "install") */
|
|
1152
|
+
label?: ReactNode;
|
|
1153
|
+
/** Hint shown on the right while idle (default: "탭하여 복사") */
|
|
1154
|
+
copyHint?: ReactNode;
|
|
1155
|
+
/** Confirmation shown after copying (default: "복사됨!") */
|
|
1156
|
+
copiedLabel?: ReactNode;
|
|
1157
|
+
/** Accent (any CSS color) for the copied state. Defaults to `var(--kit-accent)`. */
|
|
1158
|
+
accent?: string;
|
|
1159
|
+
className?: string;
|
|
1160
|
+
}
|
|
1161
|
+
/**
|
|
1162
|
+
* Tap-to-copy code block with a label and copy feedback.
|
|
1163
|
+
*
|
|
1164
|
+
* @example
|
|
1165
|
+
* <CodeBlock label="install" code="npm i @m1kapp/kit" />
|
|
1166
|
+
*/
|
|
1167
|
+
declare function CodeBlock({ code, label, copyHint, copiedLabel, accent, className, }: CodeBlockProps): react_jsx_runtime.JSX.Element;
|
|
1168
|
+
|
|
1169
|
+
interface InlineEditProps {
|
|
1170
|
+
value: string;
|
|
1171
|
+
/** Called with the trimmed value on commit (Enter or blur) */
|
|
1172
|
+
onChange: (value: string) => void;
|
|
1173
|
+
placeholder?: string;
|
|
1174
|
+
/** Disable editing — renders as plain text */
|
|
1175
|
+
readOnly?: boolean;
|
|
1176
|
+
/** Text color (any CSS color), e.g. an entity's color */
|
|
1177
|
+
color?: string;
|
|
1178
|
+
/** Class applied to both the display and the input (for shared typography) */
|
|
1179
|
+
className?: string;
|
|
1180
|
+
}
|
|
1181
|
+
/**
|
|
1182
|
+
* Tap-to-edit text. Shows the value as text; clicking turns it into an
|
|
1183
|
+
* autofocused input that commits on Enter/blur and cancels on Escape.
|
|
1184
|
+
*
|
|
1185
|
+
* @example
|
|
1186
|
+
* <InlineEdit value={name} onChange={rename} placeholder="이름" className="text-lg font-bold" />
|
|
1187
|
+
*/
|
|
1188
|
+
declare function InlineEdit({ value, onChange, placeholder, readOnly, color, className, }: InlineEditProps): react_jsx_runtime.JSX.Element;
|
|
1189
|
+
|
|
1190
|
+
interface BarListItem {
|
|
1191
|
+
label: ReactNode;
|
|
1192
|
+
value: number;
|
|
1193
|
+
/** Optional link — the label becomes an anchor */
|
|
1194
|
+
href?: string;
|
|
1195
|
+
}
|
|
1196
|
+
interface BarListProps {
|
|
1197
|
+
items: BarListItem[];
|
|
1198
|
+
/** Bar fill color (any CSS color). Defaults to `var(--kit-accent)`. */
|
|
1199
|
+
accent?: string;
|
|
1200
|
+
/** Format the trailing value (default: localized number) */
|
|
1201
|
+
formatValue?: (value: number) => ReactNode;
|
|
1202
|
+
/** Bars are sized relative to this. Default: sum of values. Pass the max for "share of peak". */
|
|
1203
|
+
total?: number;
|
|
1204
|
+
className?: string;
|
|
1205
|
+
}
|
|
1206
|
+
/**
|
|
1207
|
+
* Horizontal bar list for ranked breakdowns (top pages, referrers, tags…).
|
|
1208
|
+
* Each row is a labeled bar whose width is proportional to its value.
|
|
1209
|
+
*
|
|
1210
|
+
* @example
|
|
1211
|
+
* <BarList items={[{ label: "/", value: 120 }, { label: "/about", value: 64, href: "/about" }]} />
|
|
1212
|
+
*/
|
|
1213
|
+
declare function BarList({ items, accent, formatValue, total, className }: BarListProps): react_jsx_runtime.JSX.Element;
|
|
1214
|
+
|
|
1215
|
+
interface ProgressRingProps {
|
|
1216
|
+
/** Current value */
|
|
1217
|
+
value: number;
|
|
1218
|
+
/** Max value (default 1, so `value` is treated as a 0–1 fraction) */
|
|
1219
|
+
max?: number;
|
|
1220
|
+
/** Diameter in px (default 96) */
|
|
1221
|
+
size?: number;
|
|
1222
|
+
/** Stroke width in px (default 8) */
|
|
1223
|
+
thickness?: number;
|
|
1224
|
+
/** Progress stroke color (any CSS color). Defaults to `var(--kit-accent)`. */
|
|
1225
|
+
accent?: string;
|
|
1226
|
+
/** Center content (e.g. the number). Defaults to a percentage. */
|
|
1227
|
+
children?: ReactNode;
|
|
1228
|
+
/** Animate the stroke from empty on mount (default: true) */
|
|
1229
|
+
animate?: boolean;
|
|
1230
|
+
className?: string;
|
|
1231
|
+
}
|
|
1232
|
+
/**
|
|
1233
|
+
* Circular progress ring with a center slot. Good for scores, completion, and
|
|
1234
|
+
* quota indicators.
|
|
1235
|
+
*
|
|
1236
|
+
* @example
|
|
1237
|
+
* <ProgressRing value={7} max={10}><span className="text-2xl font-black">7</span></ProgressRing>
|
|
1238
|
+
* <ProgressRing value={0.42} size={64} />
|
|
1239
|
+
*/
|
|
1240
|
+
declare function ProgressRing({ value, max, size, thickness, accent, children, animate, className, }: ProgressRingProps): react_jsx_runtime.JSX.Element;
|
|
1241
|
+
|
|
1242
|
+
interface CountdownLabels {
|
|
1243
|
+
days?: string;
|
|
1244
|
+
hours?: string;
|
|
1245
|
+
mins?: string;
|
|
1246
|
+
secs?: string;
|
|
1247
|
+
}
|
|
1248
|
+
interface CountdownProps {
|
|
1249
|
+
/** Target time — Date, epoch ms, or ISO/parseable date string */
|
|
1250
|
+
to: Date | number | string;
|
|
1251
|
+
/** Called once when the target is reached */
|
|
1252
|
+
onComplete?: () => void;
|
|
1253
|
+
/** Render when the target has passed. Default: a "+Nd" overdue line. */
|
|
1254
|
+
renderOverdue?: (daysOverdue: number) => ReactNode;
|
|
1255
|
+
/** Hide the days cell when 0 */
|
|
1256
|
+
hideZeroDays?: boolean;
|
|
1257
|
+
labels?: CountdownLabels;
|
|
1258
|
+
/** Separator/label color (any CSS color). Defaults to `var(--kit-accent)`. */
|
|
1259
|
+
accent?: string;
|
|
1260
|
+
className?: string;
|
|
1261
|
+
}
|
|
1262
|
+
/**
|
|
1263
|
+
* Live countdown to a target time (days/hours/mins/secs), ticking each second.
|
|
1264
|
+
* Renders an SSR-safe placeholder on first paint and supports overdue display.
|
|
1265
|
+
*
|
|
1266
|
+
* @example
|
|
1267
|
+
* <Countdown to="2026-12-31" onComplete={celebrate} />
|
|
1268
|
+
* <Countdown to={deadline} hideZeroDays />
|
|
1269
|
+
*/
|
|
1270
|
+
declare function Countdown({ to, onComplete, renderOverdue, hideZeroDays, labels, accent, className, }: CountdownProps): react_jsx_runtime.JSX.Element | null;
|
|
1271
|
+
|
|
1272
|
+
interface CarouselProps {
|
|
1273
|
+
/** Total number of slides */
|
|
1274
|
+
count: number;
|
|
1275
|
+
/** Active slide index (controlled) */
|
|
1276
|
+
index: number;
|
|
1277
|
+
onChange: (index: number) => void;
|
|
1278
|
+
/** Active slide content (the caller renders based on `index`) */
|
|
1279
|
+
children: ReactNode;
|
|
1280
|
+
/** Wrap around at the ends (default: true) */
|
|
1281
|
+
loop?: boolean;
|
|
1282
|
+
showArrows?: boolean;
|
|
1283
|
+
showDots?: boolean;
|
|
1284
|
+
/** Active dot color (any CSS color). Defaults to `var(--kit-accent)`. */
|
|
1285
|
+
accent?: string;
|
|
1286
|
+
className?: string;
|
|
1287
|
+
}
|
|
1288
|
+
/**
|
|
1289
|
+
* Swipeable carousel with dot indicators and prev/next arrows. Controlled —
|
|
1290
|
+
* you hold the index and render the active slide as children.
|
|
1291
|
+
*
|
|
1292
|
+
* @example
|
|
1293
|
+
* <Carousel count={items.length} index={i} onChange={setI}>
|
|
1294
|
+
* <SlideView item={items[i]} />
|
|
1295
|
+
* </Carousel>
|
|
1296
|
+
*/
|
|
1297
|
+
declare function Carousel({ count, index, onChange, children, loop, showArrows, showDots, accent, className, }: CarouselProps): react_jsx_runtime.JSX.Element;
|
|
683
1298
|
|
|
684
1299
|
type PWAInstallState = "android-ready" | "ios-safari" | "installed" | "unsupported";
|
|
685
1300
|
interface UsePWAInstallReturn {
|
|
@@ -893,5 +1508,21 @@ declare function formatNumber(n: number): string;
|
|
|
893
1508
|
declare function formatPrice(amount: number, currency?: string, locale?: string): string;
|
|
894
1509
|
|
|
895
1510
|
declare function cn(...inputs: ClassValue[]): string;
|
|
1511
|
+
declare function formatDuration(ms: number, opts?: {
|
|
1512
|
+
style?: "short" | "clock";
|
|
1513
|
+
}): string;
|
|
1514
|
+
interface DayGroup<T> {
|
|
1515
|
+
/** YYYY-MM-DD */
|
|
1516
|
+
date: string;
|
|
1517
|
+
/** 오늘 / 어제 / "M월 D일 (요일)" */
|
|
1518
|
+
label: string;
|
|
1519
|
+
items: T[];
|
|
1520
|
+
}
|
|
1521
|
+
/**
|
|
1522
|
+
* Korean day label relative to today: "오늘" / "어제" / "4월 19일 (토)".
|
|
1523
|
+
* Shared by `groupByDay` and `MessageList`'s day dividers.
|
|
1524
|
+
*/
|
|
1525
|
+
declare function formatDayLabel(time: number | string | Date): string;
|
|
1526
|
+
declare function groupByDay<T>(items: T[], getTime: (item: T) => number | string | Date): DayGroup<T>[];
|
|
896
1527
|
|
|
897
|
-
export { type ApiClient, type ApiClientOptions, ApiError, AppShell, AppShellContent, type AppShellContentProps, AppShellHeader, type AppShellHeaderProps, type AppShellProps, Avatar, type AvatarProps, Badge, type BadgeProps, Button, type ButtonProps, type ColorName, Dialog, type DialogProps, Divider, EmojiButton, type EmojiButtonProps, EmojiPicker, type EmojiPickerLabels, type EmojiPickerProps, EmptyState, type EmptyStateProps, Fab, type FabProps, FontLinks, type FontName, GrassMap, type GrassMapData, type GrassMapLabels, type GrassMapProps, IOSInstallSheet, InAppSheet, type InAppSheetProps, KitStyles, PWAInstallButton, type PWAInstallState, PoweredByKit, type PoweredByKitProps, Section, SectionHeader, type SectionHeaderProps, type SectionProps, ShareButton, type ShareButtonProps, Skeleton, type SkeletonProps, StatChip, type StatChipProps, THEME_SCRIPT, Tab, TabBar, type TabBarProps, type TabProps, ThemeButton, type ThemeButtonProps, ThemeDialog, type ThemeDialogLabels, type ThemeDialogProps, type ToastOptions, ToastProvider, type ToastVariant, Tooltip, type TooltipProps, Typewriter, type TypewriterProps, type UseFetchOptions, type UseFetchResult, type UseFormSubmitOptions, type UseFormSubmitResult, type UseInViewOptions, type UseInViewResult, type UsePWAInstallReturn, type UsePollingOptions, type UsePollingResult, type UseShareOptions, type UseShareReturn, Watermark, type WatermarkProps, type WatermarkSponsor, clearFetchCache, cn, colors, createApiClient, createManifest, fontFamily, fonts, formatNumber, formatPrice, mobileViewport, relativeTime, svgIcon, useDebounce, useEscapeKey, useFetch, useFocusTrap, useFormSubmit, useInView, useLocalStorage, usePWAInstall, usePolling, usePortalTarget, useScrollLock, useShare, useToast };
|
|
1528
|
+
export { ActionCard, type ActionCardLabels, type ActionCardProps, type ActionCardState, type ApiClient, type ApiClientOptions, ApiError, AppShell, AppShellContent, type AppShellContentProps, AppShellHeader, type AppShellHeaderProps, type AppShellProps, Avatar, type AvatarProps, Badge, type BadgeProps, BarList, type BarListItem, type BarListProps, Button, type ButtonProps, Carousel, type CarouselProps, ChatBubble, type ChatBubbleProps, type ChatMessage, type ChatRole, CodeBlock, type CodeBlockProps, Collapsible, type CollapsibleProps, type ColorName, ColorPicker, type ColorPickerProps, CopyButton, type CopyButtonProps, Countdown, type CountdownLabels, type CountdownProps, type DayGroup, Dialog, type DialogProps, Divider, EmojiButton, type EmojiButtonProps, EmojiPicker, type EmojiPickerLabels, type EmojiPickerProps, EmptyState, type EmptyStateProps, Fab, type FabProps, Field, type FieldProps, FontLinks, type FontName, GrassMap, type GrassMapData, type GrassMapLabels, type GrassMapProps, IOSInstallSheet, Img, type ImgProps, InAppSheet, type InAppSheetProps, InlineEdit, type InlineEditProps, KitStyles, LinkifiedText, type LinkifiedTextProps, ListRow, type ListRowProps, MessageList, type MessageListProps, PWAInstallButton, type PWAInstallState, PoweredByKit, type PoweredByKitProps, ProgressRing, type ProgressRingProps, Section, SectionHeader, type SectionHeaderProps, type SectionProps, type SegmentOption, SegmentedControl, type SegmentedControlProps, Select, type SelectOption, type SelectProps, ShareButton, type ShareButtonProps, Skeleton, type SkeletonProps, StatChip, type StatChipProps, type Step, Stepper, type StepperProps, Switch, type SwitchProps, THEME_SCRIPT, Tab, TabBar, type TabBarProps, type TabProps, ThemeButton, type ThemeButtonProps, ThemeDialog, type ThemeDialogLabels, type ThemeDialogProps, type ToastOptions, ToastProvider, type ToastVariant, Tooltip, type TooltipProps, Typewriter, type TypewriterProps, TypingIndicator, type TypingIndicatorProps, type UseFetchOptions, type UseFetchResult, type UseFormSubmitOptions, type UseFormSubmitResult, type UseInViewOptions, type UseInViewResult, type UsePWAInstallReturn, type UsePollingOptions, type UsePollingResult, type UseShareOptions, type UseShareReturn, Watermark, type WatermarkProps, type WatermarkSponsor, clearFetchCache, cn, colors, createApiClient, createManifest, fontFamily, fonts, formatDayLabel, formatDuration, formatNumber, formatPrice, groupByDay, mobileViewport, relativeTime, svgIcon, useCopy, useDebounce, useEscapeKey, useFetch, useFocusTrap, useFormSubmit, useImageLoader, useInView, useLocalStorage, usePWAInstall, usePolling, usePortalTarget, useScrollLock, useShare, useToast };
|