@m1kapp/kit 0.0.9 → 0.0.10

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/pwa.d.mts ADDED
@@ -0,0 +1,102 @@
1
+ import { MetadataRoute, Viewport } from 'next';
2
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
+
4
+ type PWAInstallState = "android-ready" | "ios-safari" | "installed" | "unsupported";
5
+ interface UsePWAInstallReturn {
6
+ state: PWAInstallState;
7
+ /** Android only — triggers the native install dialog */
8
+ install(): Promise<void>;
9
+ }
10
+ declare function usePWAInstall(): UsePWAInstallReturn;
11
+
12
+ interface PWAInstallButtonProps {
13
+ /** App name shown in iOS guide sheet */
14
+ appName?: string;
15
+ /** App icon src shown in iOS guide (optional) */
16
+ iconSrc?: string;
17
+ /** Label for the install button. Default: "앱으로 설치" */
18
+ label?: string;
19
+ /** Label shown when already installed. Default: undefined — button hidden */
20
+ installedLabel?: string;
21
+ className?: string;
22
+ }
23
+ /**
24
+ * PWA install button that handles both Android and iOS.
25
+ *
26
+ * - Android (Chrome): triggers the native install dialog
27
+ * - iOS (Safari): opens a step-by-step "Add to Home Screen" guide sheet
28
+ * - Already installed: hidden by default (show with installedLabel)
29
+ * - Unsupported: hidden
30
+ *
31
+ * Usage:
32
+ * <PWAInstallButton appName="My App" iconSrc="/icon.png" />
33
+ */
34
+ declare function PWAInstallButton({ appName, iconSrc, label, installedLabel, className, }: PWAInstallButtonProps): react_jsx_runtime.JSX.Element | null;
35
+ interface IOSInstallSheetProps {
36
+ open: boolean;
37
+ onClose(): void;
38
+ appName: string;
39
+ iconSrc?: string;
40
+ }
41
+ /**
42
+ * Bottom-sheet guide for iOS "Add to Home Screen".
43
+ * Can also be used standalone if you need custom trigger UI.
44
+ */
45
+ declare function IOSInstallSheet({ open, onClose, appName, iconSrc }: IOSInstallSheetProps): react_jsx_runtime.JSX.Element | null;
46
+
47
+ /**
48
+ * Standard mobile viewport config for Next.js.
49
+ * - Disables pinch zoom via maximumScale (Android, older iOS)
50
+ * - Prevents input auto-zoom on iOS via the CSS in @m1kapp/kit (font-size: max(16px, 1em))
51
+ * - touch-action: pan-x pan-y in CSS handles iOS 10+ pinch zoom
52
+ *
53
+ * Usage: export const viewport = mobileViewport;
54
+ */
55
+ declare const mobileViewport: Viewport;
56
+ /**
57
+ * Generates an SVG icon as a data URI — no image files needed.
58
+ *
59
+ * Usage:
60
+ * svgIcon("m1k", { size: 192, bg: "#0f172a" })
61
+ * svgIcon("WP", { size: 512, bg: "#18181b", radius: 0.25 })
62
+ */
63
+ declare function svgIcon(text: string, options?: {
64
+ size?: number;
65
+ bg?: string;
66
+ color?: string;
67
+ /** Corner radius as a fraction of size. Default: 0.25 (25%) */
68
+ radius?: number;
69
+ /** Font size as a fraction of size. Default: 0.375 */
70
+ fontSize?: number;
71
+ }): string;
72
+ /**
73
+ * Generates a Next.js web app manifest (app/manifest.ts).
74
+ * Icons are auto-generated as inline SVGs — no image files needed.
75
+ *
76
+ * Usage:
77
+ * // app/manifest.ts
78
+ * import { createManifest } from "@m1kapp/kit";
79
+ * export default createManifest({
80
+ * name: "m1k",
81
+ * shortName: "m1k",
82
+ * themeColor: "#0f172a",
83
+ * icon: { text: "m1k" },
84
+ * });
85
+ */
86
+ declare function createManifest(options: {
87
+ name: string;
88
+ shortName?: string;
89
+ description?: string;
90
+ startUrl?: string;
91
+ backgroundColor?: string;
92
+ themeColor?: string;
93
+ /** Text-based icon config — generates SVG icons automatically */
94
+ icon?: {
95
+ text: string;
96
+ bg?: string;
97
+ color?: string;
98
+ radius?: number;
99
+ };
100
+ }): MetadataRoute.Manifest;
101
+
102
+ export { IOSInstallSheet, PWAInstallButton, type PWAInstallState, type UsePWAInstallReturn, createManifest, mobileViewport, svgIcon, usePWAInstall };
package/dist/pwa.d.ts ADDED
@@ -0,0 +1,102 @@
1
+ import { MetadataRoute, Viewport } from 'next';
2
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
+
4
+ type PWAInstallState = "android-ready" | "ios-safari" | "installed" | "unsupported";
5
+ interface UsePWAInstallReturn {
6
+ state: PWAInstallState;
7
+ /** Android only — triggers the native install dialog */
8
+ install(): Promise<void>;
9
+ }
10
+ declare function usePWAInstall(): UsePWAInstallReturn;
11
+
12
+ interface PWAInstallButtonProps {
13
+ /** App name shown in iOS guide sheet */
14
+ appName?: string;
15
+ /** App icon src shown in iOS guide (optional) */
16
+ iconSrc?: string;
17
+ /** Label for the install button. Default: "앱으로 설치" */
18
+ label?: string;
19
+ /** Label shown when already installed. Default: undefined — button hidden */
20
+ installedLabel?: string;
21
+ className?: string;
22
+ }
23
+ /**
24
+ * PWA install button that handles both Android and iOS.
25
+ *
26
+ * - Android (Chrome): triggers the native install dialog
27
+ * - iOS (Safari): opens a step-by-step "Add to Home Screen" guide sheet
28
+ * - Already installed: hidden by default (show with installedLabel)
29
+ * - Unsupported: hidden
30
+ *
31
+ * Usage:
32
+ * <PWAInstallButton appName="My App" iconSrc="/icon.png" />
33
+ */
34
+ declare function PWAInstallButton({ appName, iconSrc, label, installedLabel, className, }: PWAInstallButtonProps): react_jsx_runtime.JSX.Element | null;
35
+ interface IOSInstallSheetProps {
36
+ open: boolean;
37
+ onClose(): void;
38
+ appName: string;
39
+ iconSrc?: string;
40
+ }
41
+ /**
42
+ * Bottom-sheet guide for iOS "Add to Home Screen".
43
+ * Can also be used standalone if you need custom trigger UI.
44
+ */
45
+ declare function IOSInstallSheet({ open, onClose, appName, iconSrc }: IOSInstallSheetProps): react_jsx_runtime.JSX.Element | null;
46
+
47
+ /**
48
+ * Standard mobile viewport config for Next.js.
49
+ * - Disables pinch zoom via maximumScale (Android, older iOS)
50
+ * - Prevents input auto-zoom on iOS via the CSS in @m1kapp/kit (font-size: max(16px, 1em))
51
+ * - touch-action: pan-x pan-y in CSS handles iOS 10+ pinch zoom
52
+ *
53
+ * Usage: export const viewport = mobileViewport;
54
+ */
55
+ declare const mobileViewport: Viewport;
56
+ /**
57
+ * Generates an SVG icon as a data URI — no image files needed.
58
+ *
59
+ * Usage:
60
+ * svgIcon("m1k", { size: 192, bg: "#0f172a" })
61
+ * svgIcon("WP", { size: 512, bg: "#18181b", radius: 0.25 })
62
+ */
63
+ declare function svgIcon(text: string, options?: {
64
+ size?: number;
65
+ bg?: string;
66
+ color?: string;
67
+ /** Corner radius as a fraction of size. Default: 0.25 (25%) */
68
+ radius?: number;
69
+ /** Font size as a fraction of size. Default: 0.375 */
70
+ fontSize?: number;
71
+ }): string;
72
+ /**
73
+ * Generates a Next.js web app manifest (app/manifest.ts).
74
+ * Icons are auto-generated as inline SVGs — no image files needed.
75
+ *
76
+ * Usage:
77
+ * // app/manifest.ts
78
+ * import { createManifest } from "@m1kapp/kit";
79
+ * export default createManifest({
80
+ * name: "m1k",
81
+ * shortName: "m1k",
82
+ * themeColor: "#0f172a",
83
+ * icon: { text: "m1k" },
84
+ * });
85
+ */
86
+ declare function createManifest(options: {
87
+ name: string;
88
+ shortName?: string;
89
+ description?: string;
90
+ startUrl?: string;
91
+ backgroundColor?: string;
92
+ themeColor?: string;
93
+ /** Text-based icon config — generates SVG icons automatically */
94
+ icon?: {
95
+ text: string;
96
+ bg?: string;
97
+ color?: string;
98
+ radius?: number;
99
+ };
100
+ }): MetadataRoute.Manifest;
101
+
102
+ export { IOSInstallSheet, PWAInstallButton, type PWAInstallState, type UsePWAInstallReturn, createManifest, mobileViewport, svgIcon, usePWAInstall };
package/dist/pwa.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";var f=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var y=(e,n)=>{for(var i in n)f(e,i,{get:n[i],enumerable:!0})},I=(e,n,i,s)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of w(n))!z.call(e,o)&&o!==i&&f(e,o,{get:()=>n[o],enumerable:!(s=b(n,o))||s.enumerable});return e};var S=e=>I(f({},"__esModule",{value:!0}),e);var E={};y(E,{IOSInstallSheet:()=>x,PWAInstallButton:()=>v,createManifest:()=>M,mobileViewport:()=>O,svgIcon:()=>m,usePWAInstall:()=>p});module.exports=S(E);var u=require("react");function p(){let[e,n]=(0,u.useState)(null),[i,s]=(0,u.useState)(!1);(0,u.useEffect)(()=>{if(window.matchMedia("(display-mode: standalone)").matches||navigator.standalone===!0){s(!0);return}let r=d=>{d.preventDefault(),n(d)},c=()=>s(!0);return window.addEventListener("beforeinstallprompt",r),window.addEventListener("appinstalled",c),()=>{window.removeEventListener("beforeinstallprompt",r),window.removeEventListener("appinstalled",c)}},[]);let o=i?"installed":e?"android-ready":N()?"ios-safari":"unsupported";async function a(){if(!e)return;await e.prompt();let{outcome:l}=await e.userChoice;l==="accepted"&&s(!0),n(null)}return{state:o,install:a}}function N(){if(typeof navigator>"u")return!1;let e=navigator.userAgent;return/iphone|ipad|ipod/i.test(e)&&!/CriOS|FxiOS|OPiOS|EdgiOS/i.test(e)}var g=require("react");var t=require("react/jsx-runtime");function v({appName:e="\uC571",iconSrc:n,label:i="\uC571\uC73C\uB85C \uC124\uCE58",installedLabel:s,className:o}){let{state:a,install:l}=p(),[r,c]=(0,g.useState)(!1);if(a==="installed")return s?(0,t.jsxs)("div",{className:`flex items-center gap-2 text-sm text-zinc-400 ${o??""}`,children:[(0,t.jsx)(C,{}),(0,t.jsx)("span",{children:s})]}):null;if(a==="unsupported")return null;function d(){a==="android-ready"?l():a==="ios-safari"&&c(!0)}return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("button",{onClick:d,className:`flex items-center gap-2 px-4 py-2.5 rounded-xl bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900 text-sm font-semibold transition-all active:scale-95 ${o??""}`,children:[(0,t.jsx)(h,{}),(0,t.jsx)("span",{children:i}),a==="ios-safari"&&(0,t.jsx)(P,{})]}),a==="ios-safari"&&(0,t.jsx)(x,{open:r,onClose:()=>c(!1),appName:e,iconSrc:n})]})}function x({open:e,onClose:n,appName:i,iconSrc:s}){return e?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("div",{className:"fixed inset-0 z-[9998] bg-black/40 backdrop-blur-sm",onClick:n}),(0,t.jsxs)("div",{className:"fixed bottom-0 left-1/2 -translate-x-1/2 z-[9999] w-full max-w-[430px] rounded-t-2xl bg-white dark:bg-zinc-900 shadow-2xl",children:[(0,t.jsx)("div",{className:"flex justify-center pt-3 pb-1",children:(0,t.jsx)("div",{className:"w-9 h-1 rounded-full bg-zinc-200 dark:bg-zinc-700"})}),(0,t.jsxs)("div",{className:"px-5 pb-8 pt-3",children:[(0,t.jsxs)("div",{className:"flex items-center gap-3 mb-5",children:[s?(0,t.jsx)("img",{src:s,alt:i,className:"w-12 h-12 rounded-xl shadow"}):(0,t.jsx)("div",{className:"w-12 h-12 rounded-xl bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center",children:(0,t.jsx)(h,{size:22,className:"text-zinc-400"})}),(0,t.jsxs)("div",{children:[(0,t.jsxs)("p",{className:"font-bold text-zinc-900 dark:text-white text-base",children:[i," \uC124\uCE58\uD558\uAE30"]}),(0,t.jsx)("p",{className:"text-xs text-zinc-400 mt-0.5",children:"\uD648 \uD654\uBA74\uC5D0 \uCD94\uAC00\uD558\uBA74 \uC571\uCC98\uB7FC \uC0AC\uC6A9\uD560 \uC218 \uC788\uC5B4\uC694"})]})]}),(0,t.jsx)("div",{className:"space-y-3",children:[{icon:(0,t.jsx)(W,{}),text:(0,t.jsxs)(t.Fragment,{children:["\uD558\uB2E8 \uD234\uBC14\uC758 ",(0,t.jsx)("strong",{className:"text-zinc-900 dark:text-zinc-100",children:"\uACF5\uC720"})," \uBC84\uD2BC\uC744 \uD0ED\uD558\uC138\uC694"]})},{icon:(0,t.jsx)(B,{}),text:(0,t.jsxs)(t.Fragment,{children:["\uC2A4\uD06C\uB864\uD574\uC11C"," ",(0,t.jsx)("strong",{className:"text-zinc-900 dark:text-zinc-100",children:"\uD648 \uD654\uBA74\uC5D0 \uCD94\uAC00"}),"\uB97C \uD0ED\uD558\uC138\uC694"]})},{icon:(0,t.jsx)(L,{}),text:(0,t.jsxs)(t.Fragment,{children:["\uC6B0\uCE21 \uC0C1\uB2E8 ",(0,t.jsx)("strong",{className:"text-zinc-900 dark:text-zinc-100",children:"\uCD94\uAC00"}),"\uB97C \uD0ED\uD558\uBA74 \uC644\uB8CC!"]})}].map((a,l)=>(0,t.jsxs)("div",{className:"flex items-start gap-3",children:[(0,t.jsx)("div",{className:"w-8 h-8 rounded-xl bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center flex-shrink-0 text-zinc-500 dark:text-zinc-400",children:a.icon}),(0,t.jsx)("div",{className:"flex-1 pt-1",children:(0,t.jsxs)("p",{className:"text-sm text-zinc-600 dark:text-zinc-300 leading-relaxed",children:[(0,t.jsx)("span",{className:"inline-flex items-center justify-center w-4 h-4 rounded-full bg-zinc-200 dark:bg-zinc-700 text-[9px] font-bold text-zinc-500 dark:text-zinc-400 mr-1.5 flex-shrink-0",children:l+1}),a.text]})})]},l))}),(0,t.jsxs)("div",{className:"mt-5 flex items-center gap-2 px-3 py-2.5 rounded-xl bg-zinc-50 dark:bg-zinc-800",children:[(0,t.jsx)(A,{}),(0,t.jsx)("p",{className:"text-xs text-zinc-400",children:"Safari \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C\uB9CC \uD648 \uD654\uBA74 \uCD94\uAC00\uAC00 \uAC00\uB2A5\uD574\uC694"})]}),(0,t.jsx)("button",{onClick:n,className:"mt-3 w-full py-3 rounded-xl text-sm font-semibold text-zinc-500 dark:text-zinc-400 bg-zinc-100 dark:bg-zinc-800 hover:bg-zinc-200 dark:hover:bg-zinc-700 transition-colors",children:"\uB2EB\uAE30"})]})]})]}):null}function h({size:e=16,className:n=""}){return(0,t.jsxs)("svg",{width:e,height:e,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[(0,t.jsx)("path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"}),(0,t.jsx)("polyline",{points:"7 10 12 15 17 10"}),(0,t.jsx)("line",{x1:"12",y1:"15",x2:"12",y2:"3"})]})}function P(){return(0,t.jsx)("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",className:"opacity-70",children:(0,t.jsx)("polyline",{points:"9 18 15 12 9 6"})})}function C(){return(0,t.jsx)("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:(0,t.jsx)("polyline",{points:"20 6 9 17 4 12"})})}function W(){return(0,t.jsxs)("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,t.jsx)("path",{d:"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"}),(0,t.jsx)("polyline",{points:"16 6 12 2 8 6"}),(0,t.jsx)("line",{x1:"12",y1:"2",x2:"12",y2:"15"})]})}function B(){return(0,t.jsxs)("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,t.jsx)("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2"}),(0,t.jsx)("line",{x1:"12",y1:"8",x2:"12",y2:"16"}),(0,t.jsx)("line",{x1:"8",y1:"12",x2:"16",y2:"12"})]})}function L(){return(0,t.jsxs)("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,t.jsx)("polyline",{points:"9 11 12 14 22 4"}),(0,t.jsx)("path",{d:"M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"})]})}function A(){return(0,t.jsxs)("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",className:"text-zinc-400 flex-shrink-0",children:[(0,t.jsx)("circle",{cx:"12",cy:"12",r:"10"}),(0,t.jsx)("polygon",{points:"16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76"})]})}var O={width:"device-width",initialScale:1,maximumScale:1,userScalable:!1,viewportFit:"cover"};function m(e,n={}){let{size:i=192,bg:s="#000000",color:o="#ffffff",radius:a=.25,fontSize:l=.375}=n,r=Math.round(i*a),c=Math.round(i*l),d=s.replace("#","%23"),k=o.replace("#","%23");return`data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 ${i} ${i}'><rect width='${i}' height='${i}' rx='${r}' fill='${d}'/><text x='50%25' y='50%25' dominant-baseline='central' text-anchor='middle' font-family='system-ui,sans-serif' font-size='${c}' font-weight='900' fill='${k}'>${e}</text></svg>`}function M(e){let{name:n,shortName:i=n,description:s,startUrl:o="/",backgroundColor:a="#ffffff",themeColor:l="#000000",icon:r}=e,c=r?[{src:m(r.text,{size:192,bg:r.bg??l,color:r.color,radius:r.radius}),sizes:"192x192",type:"image/svg+xml"},{src:m(r.text,{size:512,bg:r.bg??l,color:r.color,radius:r.radius}),sizes:"512x512",type:"image/svg+xml"}]:[];return{name:n,short_name:i,...s&&{description:s},start_url:o,display:"standalone",orientation:"portrait",background_color:a,theme_color:l,icons:c}}0&&(module.exports={IOSInstallSheet,PWAInstallButton,createManifest,mobileViewport,svgIcon,usePWAInstall});
package/dist/pwa.mjs ADDED
@@ -0,0 +1 @@
1
+ import{useState as x,useEffect as k}from"react";function f(){let[n,r]=x(null),[i,a]=x(!1);k(()=>{if(window.matchMedia("(display-mode: standalone)").matches||navigator.standalone===!0){a(!0);return}let s=u=>{u.preventDefault(),r(u)},d=()=>a(!0);return window.addEventListener("beforeinstallprompt",s),window.addEventListener("appinstalled",d),()=>{window.removeEventListener("beforeinstallprompt",s),window.removeEventListener("appinstalled",d)}},[]);let c=i?"installed":n?"android-ready":b()?"ios-safari":"unsupported";async function o(){if(!n)return;await n.prompt();let{outcome:l}=await n.userChoice;l==="accepted"&&a(!0),r(null)}return{state:c,install:o}}function b(){if(typeof navigator>"u")return!1;let n=navigator.userAgent;return/iphone|ipad|ipod/i.test(n)&&!/CriOS|FxiOS|OPiOS|EdgiOS/i.test(n)}import{useState as w}from"react";import{Fragment as p,jsx as t,jsxs as e}from"react/jsx-runtime";function z({appName:n="\uC571",iconSrc:r,label:i="\uC571\uC73C\uB85C \uC124\uCE58",installedLabel:a,className:c}){let{state:o,install:l}=f(),[s,d]=w(!1);if(o==="installed")return a?e("div",{className:`flex items-center gap-2 text-sm text-zinc-400 ${c??""}`,children:[t(I,{}),t("span",{children:a})]}):null;if(o==="unsupported")return null;function u(){o==="android-ready"?l():o==="ios-safari"&&d(!0)}return e(p,{children:[e("button",{onClick:u,className:`flex items-center gap-2 px-4 py-2.5 rounded-xl bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900 text-sm font-semibold transition-all active:scale-95 ${c??""}`,children:[t(g,{}),t("span",{children:i}),o==="ios-safari"&&t(y,{})]}),o==="ios-safari"&&t(m,{open:s,onClose:()=>d(!1),appName:n,iconSrc:r})]})}function m({open:n,onClose:r,appName:i,iconSrc:a}){return n?e(p,{children:[t("div",{className:"fixed inset-0 z-[9998] bg-black/40 backdrop-blur-sm",onClick:r}),e("div",{className:"fixed bottom-0 left-1/2 -translate-x-1/2 z-[9999] w-full max-w-[430px] rounded-t-2xl bg-white dark:bg-zinc-900 shadow-2xl",children:[t("div",{className:"flex justify-center pt-3 pb-1",children:t("div",{className:"w-9 h-1 rounded-full bg-zinc-200 dark:bg-zinc-700"})}),e("div",{className:"px-5 pb-8 pt-3",children:[e("div",{className:"flex items-center gap-3 mb-5",children:[a?t("img",{src:a,alt:i,className:"w-12 h-12 rounded-xl shadow"}):t("div",{className:"w-12 h-12 rounded-xl bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center",children:t(g,{size:22,className:"text-zinc-400"})}),e("div",{children:[e("p",{className:"font-bold text-zinc-900 dark:text-white text-base",children:[i," \uC124\uCE58\uD558\uAE30"]}),t("p",{className:"text-xs text-zinc-400 mt-0.5",children:"\uD648 \uD654\uBA74\uC5D0 \uCD94\uAC00\uD558\uBA74 \uC571\uCC98\uB7FC \uC0AC\uC6A9\uD560 \uC218 \uC788\uC5B4\uC694"})]})]}),t("div",{className:"space-y-3",children:[{icon:t(S,{}),text:e(p,{children:["\uD558\uB2E8 \uD234\uBC14\uC758 ",t("strong",{className:"text-zinc-900 dark:text-zinc-100",children:"\uACF5\uC720"})," \uBC84\uD2BC\uC744 \uD0ED\uD558\uC138\uC694"]})},{icon:t(N,{}),text:e(p,{children:["\uC2A4\uD06C\uB864\uD574\uC11C"," ",t("strong",{className:"text-zinc-900 dark:text-zinc-100",children:"\uD648 \uD654\uBA74\uC5D0 \uCD94\uAC00"}),"\uB97C \uD0ED\uD558\uC138\uC694"]})},{icon:t(P,{}),text:e(p,{children:["\uC6B0\uCE21 \uC0C1\uB2E8 ",t("strong",{className:"text-zinc-900 dark:text-zinc-100",children:"\uCD94\uAC00"}),"\uB97C \uD0ED\uD558\uBA74 \uC644\uB8CC!"]})}].map((o,l)=>e("div",{className:"flex items-start gap-3",children:[t("div",{className:"w-8 h-8 rounded-xl bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center flex-shrink-0 text-zinc-500 dark:text-zinc-400",children:o.icon}),t("div",{className:"flex-1 pt-1",children:e("p",{className:"text-sm text-zinc-600 dark:text-zinc-300 leading-relaxed",children:[t("span",{className:"inline-flex items-center justify-center w-4 h-4 rounded-full bg-zinc-200 dark:bg-zinc-700 text-[9px] font-bold text-zinc-500 dark:text-zinc-400 mr-1.5 flex-shrink-0",children:l+1}),o.text]})})]},l))}),e("div",{className:"mt-5 flex items-center gap-2 px-3 py-2.5 rounded-xl bg-zinc-50 dark:bg-zinc-800",children:[t(C,{}),t("p",{className:"text-xs text-zinc-400",children:"Safari \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C\uB9CC \uD648 \uD654\uBA74 \uCD94\uAC00\uAC00 \uAC00\uB2A5\uD574\uC694"})]}),t("button",{onClick:r,className:"mt-3 w-full py-3 rounded-xl text-sm font-semibold text-zinc-500 dark:text-zinc-400 bg-zinc-100 dark:bg-zinc-800 hover:bg-zinc-200 dark:hover:bg-zinc-700 transition-colors",children:"\uB2EB\uAE30"})]})]})]}):null}function g({size:n=16,className:r=""}){return e("svg",{width:n,height:n,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",className:r,children:[t("path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"}),t("polyline",{points:"7 10 12 15 17 10"}),t("line",{x1:"12",y1:"15",x2:"12",y2:"3"})]})}function y(){return t("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",className:"opacity-70",children:t("polyline",{points:"9 18 15 12 9 6"})})}function I(){return t("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:t("polyline",{points:"20 6 9 17 4 12"})})}function S(){return e("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[t("path",{d:"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"}),t("polyline",{points:"16 6 12 2 8 6"}),t("line",{x1:"12",y1:"2",x2:"12",y2:"15"})]})}function N(){return e("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[t("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2"}),t("line",{x1:"12",y1:"8",x2:"12",y2:"16"}),t("line",{x1:"8",y1:"12",x2:"16",y2:"12"})]})}function P(){return e("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[t("polyline",{points:"9 11 12 14 22 4"}),t("path",{d:"M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"})]})}function C(){return e("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",className:"text-zinc-400 flex-shrink-0",children:[t("circle",{cx:"12",cy:"12",r:"10"}),t("polygon",{points:"16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76"})]})}var E={width:"device-width",initialScale:1,maximumScale:1,userScalable:!1,viewportFit:"cover"};function v(n,r={}){let{size:i=192,bg:a="#000000",color:c="#ffffff",radius:o=.25,fontSize:l=.375}=r,s=Math.round(i*o),d=Math.round(i*l),u=a.replace("#","%23"),h=c.replace("#","%23");return`data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 ${i} ${i}'><rect width='${i}' height='${i}' rx='${s}' fill='${u}'/><text x='50%25' y='50%25' dominant-baseline='central' text-anchor='middle' font-family='system-ui,sans-serif' font-size='${d}' font-weight='900' fill='${h}'>${n}</text></svg>`}function $(n){let{name:r,shortName:i=r,description:a,startUrl:c="/",backgroundColor:o="#ffffff",themeColor:l="#000000",icon:s}=n,d=s?[{src:v(s.text,{size:192,bg:s.bg??l,color:s.color,radius:s.radius}),sizes:"192x192",type:"image/svg+xml"},{src:v(s.text,{size:512,bg:s.bg??l,color:s.color,radius:s.radius}),sizes:"512x512",type:"image/svg+xml"}]:[];return{name:r,short_name:i,...a&&{description:a},start_url:c,display:"standalone",orientation:"portrait",background_color:o,theme_color:l,icons:d}}export{m as IOSInstallSheet,z as PWAInstallButton,$ as createManifest,E as mobileViewport,v as svgIcon,f as usePWAInstall};
@@ -0,0 +1,9 @@
1
+ import { ClassValue } from 'clsx';
2
+
3
+ declare function relativeTime(date: Date | string | number): string;
4
+ declare function formatNumber(n: number): string;
5
+ declare function formatPrice(amount: number, currency?: string, locale?: string): string;
6
+
7
+ declare function cn(...inputs: ClassValue[]): string;
8
+
9
+ export { cn, formatNumber, formatPrice, relativeTime };
@@ -0,0 +1,9 @@
1
+ import { ClassValue } from 'clsx';
2
+
3
+ declare function relativeTime(date: Date | string | number): string;
4
+ declare function formatNumber(n: number): string;
5
+ declare function formatPrice(amount: number, currency?: string, locale?: string): string;
6
+
7
+ declare function cn(...inputs: ClassValue[]): string;
8
+
9
+ export { cn, formatNumber, formatPrice, relativeTime };
package/dist/utils.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";var i=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var m=(t,r)=>{for(var n in r)i(t,n,{get:r[n],enumerable:!0})},l=(t,r,n,e)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of s(r))!c.call(t,o)&&o!==n&&i(t,o,{get:()=>r[o],enumerable:!(e=f(r,o))||e.enumerable});return t};var _=t=>l(i({},"__esModule",{value:!0}),t);var b={};m(b,{cn:()=>x,formatNumber:()=>g,formatPrice:()=>p,relativeTime:()=>$});module.exports=_(b);var a=require("clsx"),u=require("tailwind-merge");function $(t){let r=new Date(t),n=Date.now()-r.getTime(),e=Math.floor(n/1e3);return e<60?"\uBC29\uAE08 \uC804":e<3600?`${Math.floor(e/60)}\uBD84 \uC804`:e<86400?`${Math.floor(e/3600)}\uC2DC\uAC04 \uC804`:e<86400*2?"\uC5B4\uC81C":e<86400*7?`${Math.floor(e/86400)}\uC77C \uC804`:e<86400*30?`${Math.floor(e/(86400*7))}\uC8FC \uC804`:r.toLocaleDateString("ko-KR",{year:"numeric",month:"long",day:"numeric"})}function g(t){let r=Math.abs(t),n=t<0?"-":"";return r>=1e8?`${n}${(r/1e8).toFixed(1).replace(/\.0$/,"")}\uC5B5`:r>=1e4?`${n}${(r/1e4).toFixed(1).replace(/\.0$/,"")}\uB9CC`:r>=1e3?`${n}${(r/1e3).toFixed(1).replace(/\.0$/,"")}\uCC9C`:t.toLocaleString("ko-KR")}function p(t,r="KRW",n="ko-KR"){return new Intl.NumberFormat(n,{style:"currency",currency:r,maximumFractionDigits:r==="KRW"?0:2}).format(t)}function x(...t){return(0,u.twMerge)((0,a.clsx)(t))}0&&(module.exports={cn,formatNumber,formatPrice,relativeTime});
package/dist/utils.mjs ADDED
@@ -0,0 +1 @@
1
+ import{clsx as o}from"clsx";import{twMerge as i}from"tailwind-merge";function a(e){let r=new Date(e),n=Date.now()-r.getTime(),t=Math.floor(n/1e3);return t<60?"\uBC29\uAE08 \uC804":t<3600?`${Math.floor(t/60)}\uBD84 \uC804`:t<86400?`${Math.floor(t/3600)}\uC2DC\uAC04 \uC804`:t<86400*2?"\uC5B4\uC81C":t<86400*7?`${Math.floor(t/86400)}\uC77C \uC804`:t<86400*30?`${Math.floor(t/(86400*7))}\uC8FC \uC804`:r.toLocaleDateString("ko-KR",{year:"numeric",month:"long",day:"numeric"})}function u(e){let r=Math.abs(e),n=e<0?"-":"";return r>=1e8?`${n}${(r/1e8).toFixed(1).replace(/\.0$/,"")}\uC5B5`:r>=1e4?`${n}${(r/1e4).toFixed(1).replace(/\.0$/,"")}\uB9CC`:r>=1e3?`${n}${(r/1e3).toFixed(1).replace(/\.0$/,"")}\uCC9C`:e.toLocaleString("ko-KR")}function f(e,r="KRW",n="ko-KR"){return new Intl.NumberFormat(n,{style:"currency",currency:r,maximumFractionDigits:r==="KRW"?0:2}).format(e)}function m(...e){return i(o(e))}export{m as cn,u as formatNumber,f as formatPrice,a as relativeTime};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m1kapp/kit",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "description": "UI, SEO, and PWA utilities for side projects",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -20,6 +20,16 @@
20
20
  "types": "./dist/ogimage.d.ts",
21
21
  "import": "./dist/ogimage.mjs",
22
22
  "require": "./dist/ogimage.js"
23
+ },
24
+ "./pwa": {
25
+ "types": "./dist/pwa.d.ts",
26
+ "import": "./dist/pwa.mjs",
27
+ "require": "./dist/pwa.js"
28
+ },
29
+ "./utils": {
30
+ "types": "./dist/utils.d.ts",
31
+ "import": "./dist/utils.mjs",
32
+ "require": "./dist/utils.js"
23
33
  }
24
34
  },
25
35
  "bin": {