@m1kapp/kit 0.0.28 → 0.0.31
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/bin/skills/m1kapp-clean.md +71 -0
- package/bin/skills/m1kapp-init.md +20 -7
- package/bin/skills.mjs +4 -0
- package/bin/stats.mjs +418 -2
- package/dist/index.d.mts +296 -84
- package/dist/index.d.ts +296 -84
- package/dist/index.js +4 -4
- package/dist/index.mjs +4 -4
- package/dist/meta.json +79 -13
- package/dist/ogimage.js +1 -1
- package/dist/ogimage.mjs +1 -1
- package/dist/pwa.d.mts +12 -11
- package/dist/pwa.d.ts +12 -11
- package/dist/pwa.js +2 -2
- package/dist/pwa.mjs +2 -2
- package/dist/styles.css +1 -1
- package/dist/utils.d.mts +28 -1
- package/dist/utils.d.ts +28 -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, SyntheticEvent } from 'react';
|
|
3
|
+
import React__default, { ReactNode, CSSProperties, ReactElement, RefObject, SyntheticEvent } from 'react';
|
|
4
4
|
import { MetadataRoute, Viewport } from 'next';
|
|
5
5
|
import { ClassValue } from 'clsx';
|
|
6
6
|
|
|
@@ -113,13 +113,25 @@ interface TabBarProps {
|
|
|
113
113
|
* Sticky bottom navigation tab bar.
|
|
114
114
|
*/
|
|
115
115
|
declare function TabBar({ children, className }: TabBarProps): react_jsx_runtime.JSX.Element;
|
|
116
|
+
interface TabRootProps {
|
|
117
|
+
className: string;
|
|
118
|
+
style?: CSSProperties;
|
|
119
|
+
"aria-current"?: "page";
|
|
120
|
+
children: ReactNode;
|
|
121
|
+
}
|
|
116
122
|
interface TabProps {
|
|
117
123
|
active: boolean;
|
|
118
|
-
onClick
|
|
124
|
+
onClick?: () => void;
|
|
119
125
|
icon: ReactNode;
|
|
120
126
|
label: string;
|
|
121
127
|
/** Active tab color. Default: current text color */
|
|
122
128
|
activeColor?: string;
|
|
129
|
+
/**
|
|
130
|
+
* Render a custom root element instead of the default `<button>` —
|
|
131
|
+
* e.g. a router Link so navigations get prefetching:
|
|
132
|
+
* `render={(p) => <Link href="/store" prefetch {...p} />}`
|
|
133
|
+
*/
|
|
134
|
+
render?: (props: TabRootProps) => ReactElement;
|
|
123
135
|
}
|
|
124
136
|
/**
|
|
125
137
|
* Individual tab button for the TabBar.
|
|
@@ -130,7 +142,216 @@ interface TabProps {
|
|
|
130
142
|
* active tab is full-strength with its label tinted `activeColor`. The icon is
|
|
131
143
|
* wrapped at a consistent size so mixed emoji/SVG icons line up.
|
|
132
144
|
*/
|
|
133
|
-
declare function Tab({ active, onClick, icon, label, activeColor }: TabProps): react_jsx_runtime.JSX.Element;
|
|
145
|
+
declare function Tab({ active, onClick, icon, label, activeColor, render }: TabProps): react_jsx_runtime.JSX.Element;
|
|
146
|
+
|
|
147
|
+
interface FetchProgressProps {
|
|
148
|
+
/** Bar color. Default: `var(--kit-accent)` fallback zinc-900 */
|
|
149
|
+
color?: string;
|
|
150
|
+
/**
|
|
151
|
+
* Visual style. Default: "sweep".
|
|
152
|
+
* - `"sweep"` — a short gradient segment sweeps left-to-right in a loop
|
|
153
|
+
* (indeterminate; honest about unknown duration)
|
|
154
|
+
* - `"creep"` — nprogress-style bar that creeps toward 90%, then snaps
|
|
155
|
+
* to 100% and fades on completion
|
|
156
|
+
*/
|
|
157
|
+
variant?: "sweep" | "creep";
|
|
158
|
+
/**
|
|
159
|
+
* Explicit control. When set, overrides the global useFetch activity
|
|
160
|
+
* tracking — e.g. `active={revalidating}` for a single request's bar.
|
|
161
|
+
* When omitted, the bar shows while ANY useFetch request is in flight.
|
|
162
|
+
*/
|
|
163
|
+
active?: boolean;
|
|
164
|
+
/** Distance from the top of the positioned ancestor, in px (e.g. header height). Default: 0 */
|
|
165
|
+
top?: number;
|
|
166
|
+
/** Bar thickness in px. Default: 3 */
|
|
167
|
+
height?: number;
|
|
168
|
+
className?: string;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Slim top loading bar for stale-while-revalidate UIs — content stays
|
|
172
|
+
* visible and this bar is the only loading signal. By default it is driven
|
|
173
|
+
* by global useFetch activity (any request, including background
|
|
174
|
+
* revalidation); pass `active` to control it explicitly.
|
|
175
|
+
*
|
|
176
|
+
* Position is `absolute`, so place it inside a positioned container —
|
|
177
|
+
* e.g. directly inside `<AppShell>` (which is `relative`), with `top` set
|
|
178
|
+
* to the header height to sit just below `<AppShellHeader>`.
|
|
179
|
+
*/
|
|
180
|
+
declare function FetchProgress({ color, variant, active, top, height, className, }: FetchProgressProps): react_jsx_runtime.JSX.Element | null;
|
|
181
|
+
|
|
182
|
+
/** Manually invalidate cache entries. Pass a URL to clear one, or nothing to clear all. */
|
|
183
|
+
declare function clearFetchCache(url?: string): void;
|
|
184
|
+
/**
|
|
185
|
+
* Invalidate cached data AND force every mounted useFetch hook on that URL to
|
|
186
|
+
* refetch immediately (stale-while-revalidate: current data stays visible
|
|
187
|
+
* while the refetch runs). Pass nothing to invalidate everything.
|
|
188
|
+
*
|
|
189
|
+
* The react-query `invalidateQueries` equivalent:
|
|
190
|
+
* `await fetch("/api/weekly", { method: "POST" }); invalidateFetch("/api/weekly");`
|
|
191
|
+
*/
|
|
192
|
+
declare function invalidateFetch(url?: string): void;
|
|
193
|
+
type FetchStatus = "idle" | "loading" | "success" | "error";
|
|
194
|
+
interface UseFetchOptions<T> {
|
|
195
|
+
/** Skip fetching when false (default: true) */
|
|
196
|
+
enabled?: boolean;
|
|
197
|
+
/**
|
|
198
|
+
* Freshness window in ms (default: 0 — always stale).
|
|
199
|
+
*
|
|
200
|
+
* Results are ALWAYS cached and shown instantly on the next mount
|
|
201
|
+
* (stale-while-revalidate). `staleTime` only controls whether a
|
|
202
|
+
* background revalidation fires: within the window the cache is
|
|
203
|
+
* trusted as-is; past it, the cached data is shown immediately and
|
|
204
|
+
* refreshed in the background (`revalidating: true`).
|
|
205
|
+
*/
|
|
206
|
+
staleTime?: number;
|
|
207
|
+
/** Number of retries on network error (default: 2) */
|
|
208
|
+
retry?: number;
|
|
209
|
+
/** Base delay between retries in ms — doubles each attempt (default: 1000) */
|
|
210
|
+
retryDelay?: number;
|
|
211
|
+
/** Re-fetch when window regains focus (default: true) */
|
|
212
|
+
revalidateOnFocus?: boolean;
|
|
213
|
+
/** Custom fetcher — defaults to fetch() with JSON/text auto-parse */
|
|
214
|
+
fetcher?: (url: string) => Promise<T>;
|
|
215
|
+
onSuccess?: (data: T) => void;
|
|
216
|
+
onError?: (err: Error) => void;
|
|
217
|
+
}
|
|
218
|
+
interface UseFetchResult<T> {
|
|
219
|
+
data: T | undefined;
|
|
220
|
+
loading: boolean;
|
|
221
|
+
error: Error | undefined;
|
|
222
|
+
/**
|
|
223
|
+
* Lifecycle status:
|
|
224
|
+
* - `"idle"` — url is null/undefined or `enabled: false`
|
|
225
|
+
* - `"loading"` — fetch in progress with NO cached data to show (cold load)
|
|
226
|
+
* - `"success"` — data shown (possibly stale — see `revalidating`)
|
|
227
|
+
* - `"error"` — last fetch failed and no cached data was available
|
|
228
|
+
*/
|
|
229
|
+
status: FetchStatus;
|
|
230
|
+
/**
|
|
231
|
+
* True while a background revalidation is in flight — cached data is
|
|
232
|
+
* already displayed. Use for subtle indicators (top bar, spinner icon),
|
|
233
|
+
* NOT for replacing content.
|
|
234
|
+
*/
|
|
235
|
+
revalidating: boolean;
|
|
236
|
+
/** Manually trigger a refetch (ignores cache) */
|
|
237
|
+
refetch: () => void;
|
|
238
|
+
}
|
|
239
|
+
declare function useFetch<T>(url: string | null | undefined, options?: UseFetchOptions<T>): UseFetchResult<T>;
|
|
240
|
+
|
|
241
|
+
/** react-query 계열("pending")과 kit useFetch 계열("idle"/"loading") 상태를 모두 수용 */
|
|
242
|
+
type AsyncListStatus = FetchStatus | "pending";
|
|
243
|
+
interface AsyncListProps<T> {
|
|
244
|
+
data: T[] | undefined;
|
|
245
|
+
/** useFetch의 status를 그대로 넘기면 된다 */
|
|
246
|
+
status: AsyncListStatus;
|
|
247
|
+
error?: Error | null;
|
|
248
|
+
renderItem: (item: T, index: number) => ReactNode;
|
|
249
|
+
/** 로딩 중 반복 표시할 스켈레톤 한 개 */
|
|
250
|
+
skeleton: ReactNode;
|
|
251
|
+
skeletonCount?: number;
|
|
252
|
+
emptyMessage?: string;
|
|
253
|
+
/** 빈 상태 아래 렌더할 액션(버튼 등) */
|
|
254
|
+
emptyAction?: ReactNode;
|
|
255
|
+
className?: string;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* 비동기 목록의 4상태(로딩/에러/빈/성공)를 한 번에 처리하는 리스트.
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* const { data, status } = useFetch<Video[]>("/api/trend");
|
|
262
|
+
* <AsyncList data={data} status={status} renderItem={(v) => <VideoRow key={v.id} video={v} />}
|
|
263
|
+
* skeleton={<VideoSkeleton />} skeletonCount={5} emptyMessage="영상이 없어요" />
|
|
264
|
+
*/
|
|
265
|
+
declare function AsyncList<T>({ data, status, error, renderItem, skeleton, skeletonCount, emptyMessage, emptyAction, className, }: AsyncListProps<T>): react_jsx_runtime.JSX.Element;
|
|
266
|
+
|
|
267
|
+
type IconButtonVariant = "ghost" | "outline";
|
|
268
|
+
type IconButtonSize = "sm" | "md" | "lg";
|
|
269
|
+
interface IconButtonProps {
|
|
270
|
+
icon: ReactNode;
|
|
271
|
+
/** 접근성 라벨(aria-label) — 아이콘만 있는 버튼이므로 사실상 필수 */
|
|
272
|
+
label?: string;
|
|
273
|
+
onClick?: () => void;
|
|
274
|
+
variant?: IconButtonVariant;
|
|
275
|
+
size?: IconButtonSize;
|
|
276
|
+
disabled?: boolean;
|
|
277
|
+
className?: string;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* 아이콘 전용 정사각 버튼 — Button(텍스트용)과 달리 ghost/outline 스타일.
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* <IconButton icon={<RefreshCw size={18} />} label="새로고침" onClick={reload} />
|
|
284
|
+
*/
|
|
285
|
+
declare function IconButton({ icon, label, onClick, variant, size, disabled, className, }: IconButtonProps): react_jsx_runtime.JSX.Element;
|
|
286
|
+
|
|
287
|
+
interface InputBaseProps {
|
|
288
|
+
value: string;
|
|
289
|
+
onChange: (value: string) => void;
|
|
290
|
+
placeholder?: string;
|
|
291
|
+
disabled?: boolean;
|
|
292
|
+
onFocus?: () => void;
|
|
293
|
+
onBlur?: () => void;
|
|
294
|
+
className?: string;
|
|
295
|
+
}
|
|
296
|
+
interface InputProps extends InputBaseProps {
|
|
297
|
+
/** input type (text, email, tel, search…) */
|
|
298
|
+
type?: string;
|
|
299
|
+
onEnter?: () => void;
|
|
300
|
+
}
|
|
301
|
+
declare function Input({ value, onChange, placeholder, type, disabled, onFocus, onBlur, onEnter, className, }: InputProps): react_jsx_runtime.JSX.Element;
|
|
302
|
+
interface TextareaProps extends InputBaseProps {
|
|
303
|
+
rows?: number;
|
|
304
|
+
}
|
|
305
|
+
declare function Textarea({ value, onChange, placeholder, rows, disabled, onFocus, onBlur, className, }: TextareaProps): react_jsx_runtime.JSX.Element;
|
|
306
|
+
|
|
307
|
+
interface MediaCardProps {
|
|
308
|
+
/** 16:9 썸네일 이미지 URL */
|
|
309
|
+
thumbnail: string;
|
|
310
|
+
/** 썸네일 우하단 배지 (재생시간 등) */
|
|
311
|
+
badge?: string;
|
|
312
|
+
/** horizontal: 썸네일 좌측 절반 / vertical: 썸네일 상단 풀폭 */
|
|
313
|
+
layout?: "horizontal" | "vertical";
|
|
314
|
+
onClick?: () => void;
|
|
315
|
+
/** 제목·메타 등 본문 — 폰트/색은 호출부 소유 */
|
|
316
|
+
children: ReactNode;
|
|
317
|
+
className?: string;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* 썸네일 + 본문 미디어 카드 (영상·플레이리스트 목록용).
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* <MediaCard thumbnail={v.thumbnail} badge={v.duration} onClick={open}>
|
|
324
|
+
* <p className="text-base line-clamp-2">{v.title}</p>
|
|
325
|
+
* <p className="text-xs text-zinc-400">조회수 {formatKoreanNumber(v.viewCount)}회</p>
|
|
326
|
+
* </MediaCard>
|
|
327
|
+
*/
|
|
328
|
+
declare function MediaCard({ thumbnail, badge, layout, onClick, children, className, }: MediaCardProps): react_jsx_runtime.JSX.Element;
|
|
329
|
+
|
|
330
|
+
interface UnderlineTab<T extends string = string> {
|
|
331
|
+
id: T;
|
|
332
|
+
label: string;
|
|
333
|
+
}
|
|
334
|
+
interface UnderlineTabsProps<T extends string = string> {
|
|
335
|
+
tabs: UnderlineTab<T>[];
|
|
336
|
+
active: T;
|
|
337
|
+
onChange: (id: T) => void;
|
|
338
|
+
/** 스크롤 상단 고정 */
|
|
339
|
+
sticky?: boolean;
|
|
340
|
+
/** 좁은 탭 간격 (요일 등 짧은 라벨 다수일 때) */
|
|
341
|
+
compact?: boolean;
|
|
342
|
+
/** 활성 탭 색. Default: currentColor 기반 (dark 셸에선 white) */
|
|
343
|
+
activeColor?: string;
|
|
344
|
+
className?: string;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* 하단 언더라인 인디케이터 탭 (콘텐츠 필터용) — 하단 내비 TabBar와 별개.
|
|
348
|
+
* SegmentedControl(박스형)과 달리 미디어 앱의 카테고리 탭 UX.
|
|
349
|
+
*
|
|
350
|
+
* @example
|
|
351
|
+
* <UnderlineTabs tabs={[{ id: "all", label: "전체" }, { id: "music", label: "음악" }]}
|
|
352
|
+
* active={tab} onChange={setTab} sticky />
|
|
353
|
+
*/
|
|
354
|
+
declare function UnderlineTabs<T extends string>({ tabs, active, onChange, sticky, compact, activeColor, className, }: UnderlineTabsProps<T>): react_jsx_runtime.JSX.Element;
|
|
134
355
|
|
|
135
356
|
interface SectionProps {
|
|
136
357
|
children: ReactNode;
|
|
@@ -148,12 +369,21 @@ interface SectionHeaderProps {
|
|
|
148
369
|
*/
|
|
149
370
|
declare function SectionHeader({ children }: SectionHeaderProps): react_jsx_runtime.JSX.Element;
|
|
150
371
|
|
|
372
|
+
interface DividerProps {
|
|
373
|
+
/** 여백 프리셋. Default: "md" (mx-4 my-6 — 기존 동작) */
|
|
374
|
+
spacing?: "none" | "sm" | "md";
|
|
375
|
+
/** 선 색 (CSS color) — 클래스 충돌 없이 색만 바꿀 때 */
|
|
376
|
+
color?: string;
|
|
377
|
+
className?: string;
|
|
378
|
+
}
|
|
151
379
|
/**
|
|
152
|
-
* Horizontal divider line
|
|
380
|
+
* Horizontal divider line.
|
|
381
|
+
*
|
|
382
|
+
* @example
|
|
383
|
+
* <Divider />
|
|
384
|
+
* <Divider spacing="none" color="rgba(255,255,255,0.1)" />
|
|
153
385
|
*/
|
|
154
|
-
declare function Divider({ className }:
|
|
155
|
-
className?: string;
|
|
156
|
-
}): react_jsx_runtime.JSX.Element;
|
|
386
|
+
declare function Divider({ spacing, color, className }: DividerProps): react_jsx_runtime.JSX.Element;
|
|
157
387
|
|
|
158
388
|
interface StatChipProps {
|
|
159
389
|
label: string;
|
|
@@ -238,12 +468,7 @@ interface WatermarkProps {
|
|
|
238
468
|
total?: number;
|
|
239
469
|
};
|
|
240
470
|
}
|
|
241
|
-
/**
|
|
242
|
-
* Full-screen colored background with repeating animated text watermark pattern.
|
|
243
|
-
*
|
|
244
|
-
* Renders as a single SVG element with a <pattern> — zero extra DOM nodes per tile.
|
|
245
|
-
* Sponsor tiles inside the pattern are clickable and support hover effects.
|
|
246
|
-
*/
|
|
471
|
+
/** Estimate rendered width of a string. CJK chars ≈ 1.0×, Latin ≈ 0.62× font size. */
|
|
247
472
|
declare function Watermark({ children, color, text, maxWidth, sponsor, speed, hidePoweredBy, trackSlug, track, claimed, counts, }: WatermarkProps): react_jsx_runtime.JSX.Element;
|
|
248
473
|
|
|
249
474
|
declare const colors: {
|
|
@@ -711,7 +936,7 @@ interface PoweredByKitProps {
|
|
|
711
936
|
* No slug → no tracking (off by default). Register one with `npx m1kkit track`.
|
|
712
937
|
*/
|
|
713
938
|
slug?: string;
|
|
714
|
-
/** Tracker host. Default: "m1k.app" */
|
|
939
|
+
/** Tracker host. Default: "www.m1k.app" (apex m1k.app는 www로 307 리다이렉트 → cross-origin fetch가 CORS로 깨지므로 www 직결) */
|
|
715
940
|
trackerHost?: string;
|
|
716
941
|
/** Set false to disable the visitor beacon even when a slug is present */
|
|
717
942
|
track?: boolean;
|
|
@@ -987,18 +1212,6 @@ interface StepperProps {
|
|
|
987
1212
|
accent?: string;
|
|
988
1213
|
className?: string;
|
|
989
1214
|
}
|
|
990
|
-
/**
|
|
991
|
-
* Horizontal multi-step progress indicator with connectors. Steps before the
|
|
992
|
-
* cursor show a check, the current step is highlighted, the rest are muted.
|
|
993
|
-
* Great for wizards, multi-phase flows, and onboarding.
|
|
994
|
-
*
|
|
995
|
-
* @example
|
|
996
|
-
* <Stepper current={phase} onStepClick={setPhase} steps={[
|
|
997
|
-
* { label: "분석", icon: "📝" },
|
|
998
|
-
* { label: "준비", icon: "📸" },
|
|
999
|
-
* { label: "생성", icon: "✨" },
|
|
1000
|
-
* ]} />
|
|
1001
|
-
*/
|
|
1002
1215
|
declare function Stepper({ steps, current, completedThrough, onStepClick, accent, className, }: StepperProps): react_jsx_runtime.JSX.Element;
|
|
1003
1216
|
|
|
1004
1217
|
interface CollapsibleProps {
|
|
@@ -1020,17 +1233,6 @@ interface CollapsibleProps {
|
|
|
1020
1233
|
children: ReactNode;
|
|
1021
1234
|
className?: string;
|
|
1022
1235
|
}
|
|
1023
|
-
/**
|
|
1024
|
-
* Collapsible card with a header (leading marker, title, optional subtitle/badge)
|
|
1025
|
-
* and a body that shows when `open`. State-aware styling for expanded/completed.
|
|
1026
|
-
* Good for step lists, accordions, and disclosure sections.
|
|
1027
|
-
*
|
|
1028
|
-
* @example
|
|
1029
|
-
* <Collapsible leading={1} title="페르소나 분석" subtitle="스타일 파악"
|
|
1030
|
-
* open={open === 1} onToggle={() => setOpen(open === 1 ? null : 1)} completed>
|
|
1031
|
-
* <p>…</p>
|
|
1032
|
-
* </Collapsible>
|
|
1033
|
-
*/
|
|
1034
1236
|
declare function Collapsible({ title, subtitle, badge, leading, open, onToggle, completed, optionalTag, accent, children, className, }: CollapsibleProps): react_jsx_runtime.JSX.Element;
|
|
1035
1237
|
|
|
1036
1238
|
/**
|
|
@@ -1313,6 +1515,18 @@ interface UsePWAInstallReturn {
|
|
|
1313
1515
|
}
|
|
1314
1516
|
declare function usePWAInstall(): UsePWAInstallReturn;
|
|
1315
1517
|
|
|
1518
|
+
interface IOSInstallSheetProps {
|
|
1519
|
+
open: boolean;
|
|
1520
|
+
onClose(): void;
|
|
1521
|
+
appName: string;
|
|
1522
|
+
iconSrc?: string;
|
|
1523
|
+
}
|
|
1524
|
+
/**
|
|
1525
|
+
* Bottom-sheet guide for iOS "Add to Home Screen".
|
|
1526
|
+
* Can also be used standalone if you need custom trigger UI.
|
|
1527
|
+
*/
|
|
1528
|
+
declare function IOSInstallSheet({ open, onClose, appName, iconSrc }: IOSInstallSheetProps): react_jsx_runtime.JSX.Element | null;
|
|
1529
|
+
|
|
1316
1530
|
interface PWAInstallButtonProps {
|
|
1317
1531
|
/** App name shown in iOS guide sheet */
|
|
1318
1532
|
appName?: string;
|
|
@@ -1336,17 +1550,6 @@ interface PWAInstallButtonProps {
|
|
|
1336
1550
|
* <PWAInstallButton appName="My App" iconSrc="/icon.png" />
|
|
1337
1551
|
*/
|
|
1338
1552
|
declare function PWAInstallButton({ appName, iconSrc, label, installedLabel, className, }: PWAInstallButtonProps): react_jsx_runtime.JSX.Element | null;
|
|
1339
|
-
interface IOSInstallSheetProps {
|
|
1340
|
-
open: boolean;
|
|
1341
|
-
onClose(): void;
|
|
1342
|
-
appName: string;
|
|
1343
|
-
iconSrc?: string;
|
|
1344
|
-
}
|
|
1345
|
-
/**
|
|
1346
|
-
* Bottom-sheet guide for iOS "Add to Home Screen".
|
|
1347
|
-
* Can also be used standalone if you need custom trigger UI.
|
|
1348
|
-
*/
|
|
1349
|
-
declare function IOSInstallSheet({ open, onClose, appName, iconSrc }: IOSInstallSheetProps): react_jsx_runtime.JSX.Element | null;
|
|
1350
1553
|
|
|
1351
1554
|
/**
|
|
1352
1555
|
* Drop into <head> in your root layout to pre-load kit styles and
|
|
@@ -1453,41 +1656,23 @@ declare function createApiClient(baseUrl: string, defaults?: ApiClientOptions):
|
|
|
1453
1656
|
};
|
|
1454
1657
|
type ApiClient = ReturnType<typeof createApiClient>;
|
|
1455
1658
|
|
|
1456
|
-
/**
|
|
1457
|
-
declare function
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
onError?: (err: Error) => void;
|
|
1474
|
-
}
|
|
1475
|
-
interface UseFetchResult<T> {
|
|
1476
|
-
data: T | undefined;
|
|
1477
|
-
loading: boolean;
|
|
1478
|
-
error: Error | undefined;
|
|
1479
|
-
/**
|
|
1480
|
-
* Lifecycle status:
|
|
1481
|
-
* - `"idle"` — url is null/undefined or `enabled: false`
|
|
1482
|
-
* - `"loading"` — fetch in progress
|
|
1483
|
-
* - `"success"` — data loaded (note: data may be null if the API returned null)
|
|
1484
|
-
* - `"error"` — last fetch failed
|
|
1485
|
-
*/
|
|
1486
|
-
status: FetchStatus;
|
|
1487
|
-
/** Manually trigger a refetch (ignores cache) */
|
|
1488
|
-
refetch: () => void;
|
|
1489
|
-
}
|
|
1490
|
-
declare function useFetch<T>(url: string | null | undefined, options?: UseFetchOptions<T>): UseFetchResult<T>;
|
|
1659
|
+
/** Subscribe to fetch activity changes. Returns an unsubscribe function. */
|
|
1660
|
+
declare function subscribeFetchActivity(listener: () => void): () => void;
|
|
1661
|
+
/** Number of useFetch requests currently in flight. */
|
|
1662
|
+
declare function getFetchActiveCount(): number;
|
|
1663
|
+
|
|
1664
|
+
/**
|
|
1665
|
+
* useFetch용 POST fetcher. useFetch는 URL 문자열이 캐시 키이므로, POST 조회는
|
|
1666
|
+
* `경로#식별자` 형태로 키를 만들고 요청 시 '#' 뒤를 잘라낸다:
|
|
1667
|
+
*
|
|
1668
|
+
* @example
|
|
1669
|
+
* // 같은 경로에 body만 다른 두 조회 — 키로 캐시가 분리된다
|
|
1670
|
+
* useFetch(`/api/playlist#info:${listId}`, { fetcher: postJson({ listId, infoOnly: true }) })
|
|
1671
|
+
* useFetch(`/api/playlist#videos:${listId}`, { fetcher: postJson({ listId }) })
|
|
1672
|
+
*
|
|
1673
|
+
* invalidateFetch(`/api/playlist#videos:${listId}`)로 개별 무효화 가능.
|
|
1674
|
+
*/
|
|
1675
|
+
declare function postJson<T>(body?: unknown): (key: string) => Promise<T>;
|
|
1491
1676
|
|
|
1492
1677
|
interface UsePollingOptions<T> {
|
|
1493
1678
|
/** Polling interval in ms (default: 5000) */
|
|
@@ -1533,5 +1718,32 @@ interface DayGroup<T> {
|
|
|
1533
1718
|
*/
|
|
1534
1719
|
declare function formatDayLabel(time: number | string | Date): string;
|
|
1535
1720
|
declare function groupByDay<T>(items: T[], getTime: (item: T) => number | string | Date): DayGroup<T>[];
|
|
1721
|
+
interface DateCount {
|
|
1722
|
+
date: string;
|
|
1723
|
+
count: number;
|
|
1724
|
+
}
|
|
1725
|
+
/**
|
|
1726
|
+
* 최근 N일을 0-채움한 연속 시계열로 변환 (오늘 포함, 과거→현재 순).
|
|
1727
|
+
* 날짜 키는 "YYYY-MM-DD", 기본 KST — 차트 X축이 끊기지 않게 한다.
|
|
1728
|
+
*
|
|
1729
|
+
* @example
|
|
1730
|
+
* fillDateSeries([{ date: "2026-07-06", count: 3 }], 7)
|
|
1731
|
+
* // [{date:"2026-07-01",count:0}, …, {date:"2026-07-06",count:3}, {date:"2026-07-07",count:0}]
|
|
1732
|
+
*/
|
|
1733
|
+
declare function fillDateSeries(daily: DateCount[], days: number, timeZone?: string): DateCount[];
|
|
1734
|
+
/**
|
|
1735
|
+
* 한국식 수 축약 (내림). 조회수·좋아요 표기용 — 단위는 호출부에서
|
|
1736
|
+
* `${formatKoreanNumber(n)}회`처럼 붙인다.
|
|
1737
|
+
*/
|
|
1738
|
+
declare function formatKoreanNumber(n: number | string): string;
|
|
1739
|
+
interface IsoDuration {
|
|
1740
|
+
hours: number;
|
|
1741
|
+
minutes: number;
|
|
1742
|
+
seconds: number;
|
|
1743
|
+
}
|
|
1744
|
+
/** "PT1H2M3S" → { hours: 1, minutes: 2, seconds: 3 } */
|
|
1745
|
+
declare function parseIsoDuration(duration: string): IsoDuration;
|
|
1746
|
+
/** "PT1H2M3S" → 3723 (초) */
|
|
1747
|
+
declare function isoDurationToSec(duration: string): number;
|
|
1536
1748
|
|
|
1537
|
-
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 };
|
|
1749
|
+
export { ActionCard, type ActionCardLabels, type ActionCardProps, type ActionCardState, type ApiClient, type ApiClientOptions, ApiError, AppShell, AppShellContent, type AppShellContentProps, AppShellHeader, type AppShellHeaderProps, type AppShellProps, AsyncList, type AsyncListProps, type AsyncListStatus, 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 DateCount, type DayGroup, Dialog, type DialogProps, Divider, type DividerProps, EmojiButton, type EmojiButtonProps, EmojiPicker, type EmojiPickerLabels, type EmojiPickerProps, EmptyState, type EmptyStateProps, Fab, type FabProps, FetchProgress, type FetchProgressProps, Field, type FieldProps, FontLinks, type FontName, GrassMap, type GrassMapData, type GrassMapLabels, type GrassMapProps, IOSInstallSheet, IconButton, type IconButtonProps, Img, type ImgProps, InAppSheet, type InAppSheetProps, InlineEdit, type InlineEditProps, Input, type InputProps, type IsoDuration, KitStyles, LinkifiedText, type LinkifiedTextProps, ListRow, type ListRowProps, MediaCard, type MediaCardProps, 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, type TabRootProps, Textarea, type TextareaProps, ThemeButton, type ThemeButtonProps, ThemeDialog, type ThemeDialogLabels, type ThemeDialogProps, type ToastOptions, ToastProvider, type ToastVariant, Tooltip, type TooltipProps, Typewriter, type TypewriterProps, TypingIndicator, type TypingIndicatorProps, type UnderlineTab, UnderlineTabs, type UnderlineTabsProps, 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, fillDateSeries, fontFamily, fonts, formatDayLabel, formatDuration, formatKoreanNumber, formatNumber, formatPrice, getFetchActiveCount, groupByDay, invalidateFetch, isoDurationToSec, mobileViewport, parseIsoDuration, postJson, relativeTime, subscribeFetchActivity, svgIcon, useCopy, useDebounce, useEscapeKey, useFetch, useFocusTrap, useFormSubmit, useImageLoader, useInView, useLocalStorage, usePWAInstall, usePolling, usePortalTarget, useScrollLock, useShare, useToast };
|