pubuilder 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,27 +1,29 @@
1
1
  "use client";
2
- import { jsxs as u, jsx as n, Fragment as te } from "react/jsx-runtime";
3
- import { createContext as ce, memo as ie, useRef as $, useState as _, useEffect as I, useMemo as G, useContext as oe, useLayoutEffect as se } from "react";
4
- import { createPortal as de } from "react-dom";
5
- import { create as ue } from "zustand";
6
- import { Handle as J, Position as j, ReactFlow as pe } from "@xyflow/react";
7
- const be = "http://localhost:4816";
8
- class re extends Error {
9
- constructor(t, o) {
10
- super(t), this.code = o, this.name = "ApiError";
2
+ import { jsxs as a, jsx as e, Fragment as ne } from "react/jsx-runtime";
3
+ import { createContext as se, memo as de, useRef as H, useState as v, useEffect as A, useMemo as K, useContext as le, useLayoutEffect as ue } from "react";
4
+ import { createPortal as pe } from "react-dom";
5
+ import { normalizeIA as be } from "./config.js";
6
+ import { defineIA as et } from "./config.js";
7
+ import { create as fe } from "zustand";
8
+ import { Handle as Q, Position as V, ReactFlow as he } from "@xyflow/react";
9
+ const ge = "http://localhost:4816";
10
+ class J extends Error {
11
+ constructor(o, n) {
12
+ super(o), this.code = n, this.name = "ApiError";
11
13
  }
12
14
  }
13
- class ne {
14
- constructor(t = be) {
15
- this.baseUrl = t;
15
+ class ae {
16
+ constructor(o = ge) {
17
+ this.baseUrl = o;
16
18
  }
17
- async request(t, o) {
18
- const r = await fetch(`${this.baseUrl}${t}`, {
19
- ...o,
20
- headers: { "content-type": "application/json", ...o?.headers }
19
+ async request(o, n) {
20
+ const r = await fetch(`${this.baseUrl}${o}`, {
21
+ ...n,
22
+ headers: { "content-type": "application/json", ...n?.headers }
21
23
  });
22
24
  if (!r.ok) {
23
- const a = await r.json().catch(() => ({}));
24
- throw new re(a.message ?? `요청 실패 (${r.status})`, a.code);
25
+ const l = await r.json().catch(() => ({}));
26
+ throw new J(l.message ?? `요청 실패 (${r.status})`, l.code);
25
27
  }
26
28
  return r.status === 204 ? void 0 : await r.json();
27
29
  }
@@ -35,100 +37,47 @@ class ne {
35
37
  listSkills() {
36
38
  return this.request("/api/skills");
37
39
  }
38
- toggleSkill(t, o) {
39
- return this.request(`/api/skills/${encodeURIComponent(t)}`, { method: "PATCH", body: JSON.stringify({ enabled: o }) });
40
+ toggleSkill(o, n) {
41
+ return this.request(`/api/skills/${encodeURIComponent(o)}`, { method: "PATCH", body: JSON.stringify({ enabled: n }) });
40
42
  }
41
- uploadSkill(t, o) {
42
- return this.request("/api/skills", { method: "POST", body: JSON.stringify({ filename: t, content: o }) });
43
+ uploadSkill(o, n) {
44
+ return this.request("/api/skills", { method: "POST", body: JSON.stringify({ filename: o, content: n }) });
43
45
  }
44
- removeSkill(t) {
45
- return this.request(`/api/skills/${encodeURIComponent(t)}`, { method: "DELETE" });
46
+ removeSkill(o) {
47
+ return this.request(`/api/skills/${encodeURIComponent(o)}`, { method: "DELETE" });
46
48
  }
47
49
  tokenStatus() {
48
50
  return this.request("/api/settings/figma-token");
49
51
  }
50
- saveToken(t) {
51
- return this.request("/api/settings/figma-token", { method: "PUT", body: JSON.stringify({ token: t }) });
52
+ saveToken(o) {
53
+ return this.request("/api/settings/figma-token", { method: "PUT", body: JSON.stringify({ token: o }) });
52
54
  }
53
55
  deleteToken() {
54
56
  return this.request("/api/settings/figma-token", { method: "DELETE" });
55
57
  }
56
- startPublish(t) {
57
- return this.request("/api/publish", { method: "POST", body: JSON.stringify(t) });
58
+ startPublish(o) {
59
+ return this.request("/api/publish", { method: "POST", body: JSON.stringify(o) });
58
60
  }
59
- cancelPublish(t) {
60
- return this.request(`/api/publish/${t}`, { method: "DELETE" });
61
+ cancelPublish(o) {
62
+ return this.request(`/api/publish/${o}`, { method: "DELETE" });
61
63
  }
62
64
  /** SSE 구독 — 반환값 호출로 해제 */
63
- subscribePublish(t, o) {
64
- const r = new EventSource(`${this.baseUrl}/api/publish/${t}/events`);
65
- let a = !1;
66
- return r.onmessage = (c) => {
67
- const i = JSON.parse(c.data);
68
- (i.type === "done" || i.type === "error") && (a = !0), o(i);
65
+ subscribePublish(o, n) {
66
+ const r = new EventSource(`${this.baseUrl}/api/publish/${o}/events`);
67
+ let l = !1;
68
+ return r.onmessage = (s) => {
69
+ const c = JSON.parse(s.data);
70
+ (c.type === "done" || c.type === "error") && (l = !0), n(c);
69
71
  }, r.onerror = () => {
70
- r.close(), a || (a = !0, o({ type: "error", text: "서버 연결이 끊겼어요. pubuilder serve 상태를 확인해주세요" }));
72
+ r.close(), l || (l = !0, n({ type: "error", text: "서버 연결이 끊겼어요. pubuilder serve 상태를 확인해주세요" }));
71
73
  }, () => r.close();
72
74
  }
73
75
  }
74
- const Y = ce(new ne());
75
- function Je(e) {
76
- return e;
77
- }
78
- const fe = { width: 1440, height: 900 };
79
- function X(e, t, o) {
80
- o != null && e.append(t, String(o));
81
- }
82
- function he(e, t) {
83
- const o = e.indexOf("#"), r = o >= 0 ? e.slice(o) : "", a = o >= 0 ? e.slice(0, o) : e, c = a.indexOf("?"), i = c >= 0 ? a.slice(0, c) : a, l = new URLSearchParams(c >= 0 ? a.slice(c + 1) : "");
84
- for (const [s, x] of Object.entries(t.query))
85
- if (l.delete(s), Array.isArray(x))
86
- for (const f of x) X(l, s, f);
87
- else
88
- X(l, s, x);
89
- const p = l.toString();
90
- return `${i}${p ? `?${p}` : ""}${r}`;
91
- }
92
- function ge(e) {
93
- const t = [], o = /* @__PURE__ */ new Set(), r = (a, c, i) => {
94
- for (const l of a) {
95
- if (!l.path) throw new Error("[pubuilder] page.path는 필수입니다");
96
- if (!l.title) throw new Error(`[pubuilder] "${l.path}"의 title이 없습니다`);
97
- if (o.has(l.path)) throw new Error(`[pubuilder] 중복 path: ${l.path}`);
98
- if (o.add(l.path), t.push({
99
- id: l.path,
100
- path: l.path,
101
- title: l.title,
102
- external: l.external ?? /^https?:\/\//.test(l.path),
103
- parentId: c,
104
- depth: i
105
- }), l.variants?.length) {
106
- if (l.external ?? /^https?:\/\//.test(l.path))
107
- throw new Error(`[pubuilder] 외부 페이지에는 variants를 사용할 수 없습니다: ${l.path}`);
108
- for (const p of l.variants) {
109
- if (!p.title) throw new Error(`[pubuilder] "${l.path}" variant의 title이 없습니다`);
110
- const s = he(l.path, p);
111
- if (o.has(s)) throw new Error(`[pubuilder] 중복 path: ${s}`);
112
- o.add(s), t.push({
113
- id: s,
114
- path: s,
115
- title: p.title,
116
- external: !1,
117
- parentId: l.path,
118
- depth: i + 1
119
- });
120
- }
121
- }
122
- l.children?.length && r(l.children, l.path, i + 1);
123
- }
124
- };
125
- if (r(e.pages, null, 0), t.length === 0) throw new Error("[pubuilder] pages가 비어 있습니다");
126
- return { nodes: t, viewport: e.viewport ?? fe };
127
- }
76
+ const Z = se(new ae());
128
77
  function xe() {
129
78
  return typeof process < "u" && process.env.NODE_ENV === "production";
130
79
  }
131
- const y = ue((e) => ({
80
+ const k = fe((t) => ({
132
81
  isMapOpen: !1,
133
82
  viewerPath: null,
134
83
  granularity: "section",
@@ -136,14 +85,14 @@ const y = ue((e) => ({
136
85
  selection: null,
137
86
  selectedOuterHTML: null,
138
87
  skillDrawerOpen: !1,
139
- openMap: () => e({ isMapOpen: !0 }),
140
- closeMap: () => e({ isMapOpen: !1, viewerPath: null, selection: null, selectedOuterHTML: null }),
141
- openViewer: (t) => e({ viewerPath: t, selection: null, selectedOuterHTML: null }),
142
- closeViewer: () => e({ viewerPath: null, selection: null, selectedOuterHTML: null }),
143
- setGranularity: (t) => e({ granularity: t }),
144
- setInspectEnabled: (t) => e({ inspectEnabled: t }),
145
- setSelectionWithHTML: (t, o) => e({ selection: t, selectedOuterHTML: o }),
146
- toggleSkillDrawer: () => e((t) => ({ skillDrawerOpen: !t.skillDrawerOpen }))
88
+ openMap: () => t({ isMapOpen: !0 }),
89
+ closeMap: () => t({ isMapOpen: !1, viewerPath: null, selection: null, selectedOuterHTML: null }),
90
+ openViewer: (o) => t({ viewerPath: o, selection: null, selectedOuterHTML: null }),
91
+ closeViewer: () => t({ viewerPath: null, selection: null, selectedOuterHTML: null }),
92
+ setGranularity: (o) => t({ granularity: o }),
93
+ setInspectEnabled: (o) => t({ inspectEnabled: o }),
94
+ setSelectionWithHTML: (o, n) => t({ selection: o, selectedOuterHTML: n }),
95
+ toggleSkillDrawer: () => t((o) => ({ skillDrawerOpen: !o.skillDrawerOpen }))
147
96
  })), me = ".react-flow{direction:ltr;--xy-edge-stroke-default: #b1b1b7;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #555;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(255, 255, 255, .5);--xy-minimap-background-color-default: #fff;--xy-minimap-mask-background-color-default: rgba(240, 240, 240, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #e2e2e2;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: transparent;--xy-background-pattern-dots-color-default: #91919a;--xy-background-pattern-lines-color-default: #eee;--xy-background-pattern-cross-color-default: #e2e2e2;background-color:var(--xy-background-color, var(--xy-background-color-default));--xy-node-color-default: inherit;--xy-node-border-default: 1px solid #1a192b;--xy-node-background-color-default: #fff;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(0, 0, 0, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #1a192b;--xy-node-border-radius-default: 3px;--xy-handle-background-color-default: #1a192b;--xy-handle-border-color-default: #fff;--xy-selection-background-color-default: rgba(0, 89, 220, .08);--xy-selection-border-default: 1px dotted rgba(0, 89, 220, .8);--xy-controls-button-background-color-default: #fefefe;--xy-controls-button-background-color-hover-default: #f4f4f4;--xy-controls-button-color-default: inherit;--xy-controls-button-color-hover-default: inherit;--xy-controls-button-border-color-default: #eee;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #ffffff;--xy-edge-label-color-default: inherit;--xy-resize-background-color-default: #3367d9}.react-flow.dark{--xy-edge-stroke-default: #3e3e3e;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #727272;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(150, 150, 150, .25);--xy-minimap-background-color-default: #141414;--xy-minimap-mask-background-color-default: rgba(60, 60, 60, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #2b2b2b;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: #141414;--xy-background-pattern-dots-color-default: #555;--xy-background-pattern-lines-color-default: #333;--xy-background-pattern-cross-color-default: #333;--xy-node-color-default: #f8f8f8;--xy-node-border-default: 1px solid #3c3c3c;--xy-node-background-color-default: #1e1e1e;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(255, 255, 255, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #999;--xy-handle-background-color-default: #bebebe;--xy-handle-border-color-default: #1e1e1e;--xy-selection-background-color-default: rgba(200, 200, 220, .08);--xy-selection-border-default: 1px dotted rgba(200, 200, 220, .8);--xy-controls-button-background-color-default: #2b2b2b;--xy-controls-button-background-color-hover-default: #3e3e3e;--xy-controls-button-color-default: #f8f8f8;--xy-controls-button-color-hover-default: #fff;--xy-controls-button-border-color-default: #5b5b5b;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #141414;--xy-edge-label-color-default: #f8f8f8}.react-flow__background{background-color:var(--xy-background-color-props, var(--xy-background-color, var(--xy-background-color-default)));pointer-events:none;z-index:-1}.react-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.react-flow__pane{z-index:1;touch-action:none}.react-flow__pane.draggable{cursor:grab}.react-flow__pane.dragging{cursor:grabbing}.react-flow__pane.selection{cursor:pointer}.react-flow__viewport{transform-origin:0 0;z-index:2;pointer-events:none}.react-flow__renderer{z-index:4}.react-flow__selection{z-index:6}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible{outline:none}.react-flow__edge-path{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default));stroke-width:var(--xy-edge-stroke-width, var(--xy-edge-stroke-width-default));fill:none}.react-flow__connection-path{stroke:var(--xy-connectionline-stroke, var(--xy-connectionline-stroke-default));stroke-width:var(--xy-connectionline-stroke-width, var(--xy-connectionline-stroke-width-default));fill:none}.react-flow .react-flow__edges{position:absolute}.react-flow .react-flow__edges svg{overflow:visible;position:absolute;pointer-events:none}.react-flow__edge{pointer-events:visibleStroke}.react-flow__edge.selectable{cursor:pointer}.react-flow__edge.animated path{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.react-flow__edge.animated path.react-flow__edge-interaction{stroke-dasharray:none;animation:none}.react-flow__edge.inactive{pointer-events:none}.react-flow__edge.selected,.react-flow__edge:focus,.react-flow__edge:focus-visible{outline:none}.react-flow__edge.selected .react-flow__edge-path,.react-flow__edge.selectable:focus .react-flow__edge-path,.react-flow__edge.selectable:focus-visible .react-flow__edge-path{stroke:var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default))}.react-flow__edge-textwrapper{pointer-events:all}.react-flow__edge .react-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__arrowhead polyline{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__arrowhead polyline.arrowclosed{fill:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__connection{pointer-events:none}.react-flow__connection .animated{stroke-dasharray:5;animation:dashdraw .5s linear infinite}svg.react-flow__connectionline{z-index:1001;overflow:visible;position:absolute}.react-flow__nodes{pointer-events:none;transform-origin:0 0}.react-flow__node{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:default}.react-flow__node.selectable{cursor:pointer}.react-flow__node.draggable{cursor:grab;pointer-events:all}.react-flow__node.draggable.dragging{cursor:grabbing}.react-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.react-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:grab}.react-flow__handle{position:absolute;pointer-events:none;min-width:5px;min-height:5px;width:6px;height:6px;background-color:var(--xy-handle-background-color, var(--xy-handle-background-color-default));border:1px solid var(--xy-handle-border-color, var(--xy-handle-border-color-default));border-radius:100%}.react-flow__handle.connectingfrom{pointer-events:all}.react-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.react-flow__handle-bottom{top:auto;left:50%;bottom:0;transform:translate(-50%,50%)}.react-flow__handle-top{top:0;left:50%;transform:translate(-50%,-50%)}.react-flow__handle-left{top:50%;left:0;transform:translate(-50%,-50%)}.react-flow__handle-right{top:50%;right:0;transform:translate(50%,-50%)}.react-flow__edgeupdater{cursor:move;pointer-events:all}.react-flow__pane.selection .react-flow__panel{pointer-events:none}.react-flow__panel{position:absolute;z-index:5;margin:15px}.react-flow__panel.top{top:0}.react-flow__panel.bottom{bottom:0}.react-flow__panel.top.center,.react-flow__panel.bottom.center{left:50%;transform:translate(-15px) translate(-50%)}.react-flow__panel.left{left:0}.react-flow__panel.right{right:0}.react-flow__panel.left.center,.react-flow__panel.right.center{top:50%;transform:translateY(-15px) translateY(-50%)}.react-flow__attribution{font-size:10px;background:var(--xy-attribution-background-color, var(--xy-attribution-background-color-default));padding:2px 3px;margin:0}.react-flow__attribution a{text-decoration:none;color:#999}@keyframes dashdraw{0%{stroke-dashoffset:10}}.react-flow__edgelabel-renderer{position:absolute;width:100%;height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;left:0;top:0}.react-flow__viewport-portal{position:absolute;width:100%;height:100%;left:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__minimap{background:var( --xy-minimap-background-color-props, var(--xy-minimap-background-color, var(--xy-minimap-background-color-default)) )}.react-flow__minimap-svg{display:block}.react-flow__minimap-mask{fill:var( --xy-minimap-mask-background-color-props, var(--xy-minimap-mask-background-color, var(--xy-minimap-mask-background-color-default)) );stroke:var( --xy-minimap-mask-stroke-color-props, var(--xy-minimap-mask-stroke-color, var(--xy-minimap-mask-stroke-color-default)) );stroke-width:var( --xy-minimap-mask-stroke-width-props, var(--xy-minimap-mask-stroke-width, var(--xy-minimap-mask-stroke-width-default)) )}.react-flow__minimap-node{fill:var( --xy-minimap-node-background-color-props, var(--xy-minimap-node-background-color, var(--xy-minimap-node-background-color-default)) );stroke:var( --xy-minimap-node-stroke-color-props, var(--xy-minimap-node-stroke-color, var(--xy-minimap-node-stroke-color-default)) );stroke-width:var( --xy-minimap-node-stroke-width-props, var(--xy-minimap-node-stroke-width, var(--xy-minimap-node-stroke-width-default)) )}.react-flow__background-pattern.dots{fill:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-dots-color-default)) )}.react-flow__background-pattern.lines{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-lines-color-default)) )}.react-flow__background-pattern.cross{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-cross-color-default)) )}.react-flow__controls{display:flex;flex-direction:column;box-shadow:var(--xy-controls-box-shadow, var(--xy-controls-box-shadow-default))}.react-flow__controls.horizontal{flex-direction:row}.react-flow__controls-button{display:flex;justify-content:center;align-items:center;height:26px;width:26px;padding:4px;border:none;background:var(--xy-controls-button-background-color, var(--xy-controls-button-background-color-default));border-bottom:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) );color:var( --xy-controls-button-color-props, var(--xy-controls-button-color, var(--xy-controls-button-color-default)) );cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__controls-button svg{width:100%;max-width:12px;max-height:12px;fill:currentColor}.react-flow__edge.updating .react-flow__edge-path{stroke:#777}.react-flow__edge-text{font-size:10px}.react-flow__node.selectable:focus,.react-flow__node.selectable:focus-visible{outline:none}.react-flow__node-input,.react-flow__node-default,.react-flow__node-output,.react-flow__node-group{padding:10px;border-radius:var(--xy-node-border-radius, var(--xy-node-border-radius-default));width:150px;font-size:12px;color:var(--xy-node-color, var(--xy-node-color-default));text-align:center;border:var(--xy-node-border, var(--xy-node-border-default));background-color:var(--xy-node-background-color, var(--xy-node-background-color-default))}.react-flow__node-input.selectable:hover,.react-flow__node-default.selectable:hover,.react-flow__node-output.selectable:hover,.react-flow__node-group.selectable:hover{box-shadow:var(--xy-node-boxshadow-hover, var(--xy-node-boxshadow-hover-default))}.react-flow__node-input.selectable.selected,.react-flow__node-input.selectable:focus,.react-flow__node-input.selectable:focus-visible,.react-flow__node-default.selectable.selected,.react-flow__node-default.selectable:focus,.react-flow__node-default.selectable:focus-visible,.react-flow__node-output.selectable.selected,.react-flow__node-output.selectable:focus,.react-flow__node-output.selectable:focus-visible,.react-flow__node-group.selectable.selected,.react-flow__node-group.selectable:focus,.react-flow__node-group.selectable:focus-visible{box-shadow:var(--xy-node-boxshadow-selected, var(--xy-node-boxshadow-selected-default))}.react-flow__node-group{background-color:var(--xy-node-group-background-color, var(--xy-node-group-background-color-default))}.react-flow__nodesselection-rect,.react-flow__selection{background:var(--xy-selection-background-color, var(--xy-selection-background-color-default));border:var(--xy-selection-border, var(--xy-selection-border-default))}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible,.react-flow__selection:focus,.react-flow__selection:focus-visible{outline:none}.react-flow__controls-button:hover{background:var( --xy-controls-button-background-color-hover-props, var(--xy-controls-button-background-color-hover, var(--xy-controls-button-background-color-hover-default)) );color:var( --xy-controls-button-color-hover-props, var(--xy-controls-button-color-hover, var(--xy-controls-button-color-hover-default)) )}.react-flow__controls-button:disabled{pointer-events:none}.react-flow__controls-button:disabled svg{fill-opacity:.4}.react-flow__controls-button:last-child{border-bottom:none}.react-flow__controls.horizontal .react-flow__controls-button{border-bottom:none;border-right:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) )}.react-flow__controls.horizontal .react-flow__controls-button:last-child{border-right:none}.react-flow__resize-control{position:absolute}.react-flow__resize-control.left,.react-flow__resize-control.right{cursor:ew-resize}.react-flow__resize-control.top,.react-flow__resize-control.bottom{cursor:ns-resize}.react-flow__resize-control.top.left,.react-flow__resize-control.bottom.right{cursor:nwse-resize}.react-flow__resize-control.bottom.left,.react-flow__resize-control.top.right{cursor:nesw-resize}.react-flow__resize-control.handle{width:5px;height:5px;border:1px solid #fff;border-radius:1px;background-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));translate:-50% -50%}.react-flow__resize-control.handle.left{left:0;top:50%}.react-flow__resize-control.handle.right{left:100%;top:50%}.react-flow__resize-control.handle.top{left:50%;top:0}.react-flow__resize-control.handle.bottom{left:50%;top:100%}.react-flow__resize-control.handle.top.left,.react-flow__resize-control.handle.bottom.left{left:0}.react-flow__resize-control.handle.top.right,.react-flow__resize-control.handle.bottom.right{left:100%}.react-flow__resize-control.line{border-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));border-width:0;border-style:solid}.react-flow__resize-control.line.left,.react-flow__resize-control.line.right{width:1px;transform:translate(-50%);top:0;height:100%}.react-flow__resize-control.line.left{left:0;border-left-width:1px}.react-flow__resize-control.line.right{left:100%;border-right-width:1px}.react-flow__resize-control.line.top,.react-flow__resize-control.line.bottom{height:1px;transform:translateY(-50%);left:0;width:100%}.react-flow__resize-control.line.top{top:0;border-top-width:1px}.react-flow__resize-control.line.bottom{border-bottom-width:1px;top:100%}.react-flow__edge-textbg{fill:var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default))}.react-flow__edge-text{fill:var(--xy-edge-label-color, var(--xy-edge-label-color-default))}", we = "pubuilder-styles", ye = "pubuilder-xyflow-styles", ve = (
148
97
  /* css */
149
98
  `
@@ -392,7 +341,14 @@ const y = ue((e) => ({
392
341
  flex-direction: column;
393
342
  gap: 8px;
394
343
  }
395
- .pbu-publish > label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: #8c8c8c; }
344
+ .pbu-publish-heading {
345
+ display: flex;
346
+ align-items: center;
347
+ justify-content: space-between;
348
+ gap: 8px;
349
+ }
350
+ .pbu-publish-heading > label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: #8c8c8c; }
351
+ .pbu-skill-entry { white-space: nowrap; }
396
352
  .pbu-publish input {
397
353
  background: #1e1e1e;
398
354
  border: 1px solid #3c3c3c;
@@ -419,6 +375,43 @@ const y = ue((e) => ({
419
375
  .pbu-log-tool { color: #8c8c8c; }
420
376
  .pbu-log-error { color: #f2b3b3; }
421
377
  .pbu-log-done { color: #89d185; font-weight: 600; }
378
+ .pbu-publish-reply {
379
+ padding-top: 8px;
380
+ border-top: 1px solid #3c3c3c;
381
+ display: flex;
382
+ flex-direction: column;
383
+ gap: 6px;
384
+ }
385
+ .pbu-publish-reply > label {
386
+ color: #cccccc;
387
+ font-size: 11px;
388
+ font-weight: 600;
389
+ }
390
+ .pbu-publish-reply textarea {
391
+ width: 100%;
392
+ min-height: 62px;
393
+ resize: vertical;
394
+ box-sizing: border-box;
395
+ background: #1e1e1e;
396
+ border: 1px solid #4b4b4b;
397
+ border-radius: 2px;
398
+ color: #e6e6e6;
399
+ font: 11px/1.5 ui-monospace, Menlo, monospace;
400
+ padding: 7px 8px;
401
+ outline: none;
402
+ }
403
+ .pbu-publish-reply textarea:focus {
404
+ border-color: #3794ff;
405
+ box-shadow: 0 0 0 1px #3794ff;
406
+ }
407
+ .pbu-publish-reply textarea::placeholder { color: #6f6f6f; }
408
+ .pbu-publish-reply-actions {
409
+ display: flex;
410
+ align-items: center;
411
+ justify-content: space-between;
412
+ gap: 8px;
413
+ }
414
+ .pbu-publish-reply-actions > span { color: #777; font-size: 9px; }
422
415
 
423
416
  .pbu-drawer {
424
417
  position: fixed;
@@ -445,6 +438,50 @@ const y = ue((e) => ({
445
438
  padding-bottom: 8px;
446
439
  border-bottom: 1px solid #3c3c3c;
447
440
  }
441
+ .pbu-drawer-header > div { display: flex; flex-direction: column; gap: 2px; }
442
+ .pbu-drawer-kicker { color: #858585; font-size: 9px; letter-spacing: 0.04em; }
443
+ .pbu-drawer-guide {
444
+ background: #1e1e1e;
445
+ border: 1px solid #3c3c3c;
446
+ border-left: 2px solid #3794ff;
447
+ padding: 10px;
448
+ display: flex;
449
+ flex-direction: column;
450
+ gap: 5px;
451
+ line-height: 1.45;
452
+ }
453
+ .pbu-drawer-guide strong { color: #e5e5e5; font-size: 11px; }
454
+ .pbu-drawer-guide > span { color: #9d9d9d; font-size: 10px; }
455
+ .pbu-guide-status { color: #cccccc; font-size: 10px; display: flex; align-items: center; gap: 5px; margin-top: 2px; }
456
+ .pbu-status-dot { width: 6px; height: 6px; border-radius: 50%; background: #777; }
457
+ .pbu-status-dot-on { background: #73c991; box-shadow: 0 0 0 2px rgba(115, 201, 145, 0.12); }
458
+ .pbu-drawer-section-head {
459
+ margin-top: 4px;
460
+ padding-bottom: 7px;
461
+ border-bottom: 1px solid #3c3c3c;
462
+ display: flex;
463
+ align-items: flex-start;
464
+ justify-content: space-between;
465
+ gap: 8px;
466
+ }
467
+ .pbu-drawer-section-head > div { display: flex; flex-direction: column; gap: 2px; }
468
+ .pbu-drawer-section-head strong { color: #e5e5e5; font-size: 11px; }
469
+ .pbu-drawer-section-head div > span { color: #858585; font-size: 9px; line-height: 1.4; }
470
+ .pbu-drawer-section-head-skills { margin-top: 10px; }
471
+ .pbu-status-badge, .pbu-skill-state {
472
+ flex: none;
473
+ border: 1px solid #4a4a4a;
474
+ border-radius: 999px;
475
+ padding: 1px 6px;
476
+ color: #8c8c8c;
477
+ font-size: 9px;
478
+ line-height: 1.5;
479
+ }
480
+ .pbu-status-on, .pbu-skill-state-on { border-color: #3e7651; background: #23362a; color: #89d185; }
481
+ .pbu-status-off { border-color: #765f3e; background: #382f22; color: #cca96a; }
482
+ .pbu-skill-source { margin: 8px 0 4px; display: flex; flex-direction: column; gap: 1px; }
483
+ .pbu-skill-source strong { color: #cccccc; font-size: 10px; }
484
+ .pbu-skill-source span { color: #777; font-size: 9px; line-height: 1.35; }
448
485
  .pbu-drawer-group {
449
486
  display: flex;
450
487
  align-items: center;
@@ -509,119 +546,118 @@ const y = ue((e) => ({
509
546
  }
510
547
  `
511
548
  );
512
- function K(e, t) {
513
- if (document.getElementById(e)) return;
514
- const o = document.createElement("style");
515
- o.id = e, o.textContent = t, document.head.appendChild(o);
549
+ function ee(t, o) {
550
+ if (document.getElementById(t)) return;
551
+ const n = document.createElement("style");
552
+ n.id = t, n.textContent = o, document.head.appendChild(n);
516
553
  }
517
554
  function ke() {
518
- typeof document > "u" || (K(ye, me), K(we, ve));
555
+ typeof document > "u" || (ee(ye, me), ee(we, ve));
519
556
  }
520
- function _e(e, t, o, r = 140, a = 48) {
521
- const c = /* @__PURE__ */ new Map();
522
- for (const s of e) {
523
- const x = c.get(s.parentId) ?? [];
524
- x.push(s), c.set(s.parentId, x);
557
+ function _e(t, o, n, r = 140, l = 48) {
558
+ const s = /* @__PURE__ */ new Map();
559
+ for (const g of t) {
560
+ const p = s.get(g.parentId) ?? [];
561
+ p.push(g), s.set(g.parentId, p);
525
562
  }
526
- const i = /* @__PURE__ */ new Map();
527
- let l = 0;
528
- const p = (s) => {
529
- const x = c.get(s.id) ?? [], f = s.depth * (t + r);
530
- let v;
531
- if (x.length === 0)
532
- v = l, l += o + a;
563
+ const c = /* @__PURE__ */ new Map();
564
+ let i = 0;
565
+ const f = (g) => {
566
+ const p = s.get(g.id) ?? [], m = g.depth * (o + r);
567
+ let _;
568
+ if (p.length === 0)
569
+ _ = i, i += n + l;
533
570
  else {
534
- const N = x.map(p);
535
- v = (Math.min(...N) + Math.max(...N)) / 2;
571
+ const d = p.map(f);
572
+ _ = (Math.min(...d) + Math.max(...d)) / 2;
536
573
  }
537
- return i.set(s.id, { x: f, y: v }), v;
574
+ return c.set(g.id, { x: m, y: _ }), _;
538
575
  };
539
- for (const s of c.get(null) ?? []) p(s);
540
- return e.map((s) => ({ ...s, ...i.get(s.id) }));
541
- }
542
- const Ne = ie(function(t) {
543
- const { page: o, viewport: r, thumbWidth: a, bodyHeight: c } = t.data, i = y((v) => v.openViewer), l = $(null), [p, s] = _(!1);
544
- I(() => {
545
- const v = l.current;
546
- if (!v || o.external) return;
547
- const N = new IntersectionObserver(([g]) => {
548
- g.isIntersecting && (s(!0), N.disconnect());
576
+ for (const g of s.get(null) ?? []) f(g);
577
+ return t.map((g) => ({ ...g, ...c.get(g.id) }));
578
+ }
579
+ const Ne = de(function(o) {
580
+ const { page: n, viewport: r, thumbWidth: l, bodyHeight: s } = o.data, c = k((_) => _.openViewer), i = H(null), [f, g] = v(!1);
581
+ A(() => {
582
+ const _ = i.current;
583
+ if (!_ || n.external) return;
584
+ const d = new IntersectionObserver(([C]) => {
585
+ C.isIntersecting && (g(!0), d.disconnect());
549
586
  });
550
- return N.observe(v), () => N.disconnect();
551
- }, [o.external]);
552
- const x = a / r.width;
553
- return /* @__PURE__ */ u("div", { ref: l, className: "pbu-node", style: { width: a }, onClick: () => {
554
- o.external ? window.open(o.path, "_blank", "noopener") : i(o.path);
587
+ return d.observe(_), () => d.disconnect();
588
+ }, [n.external]);
589
+ const p = l / r.width;
590
+ return /* @__PURE__ */ a("div", { ref: i, className: "pbu-node", style: { width: l }, onClick: () => {
591
+ n.external ? window.open(n.path, "_blank", "noopener") : c(n.path);
555
592
  }, children: [
556
- /* @__PURE__ */ n(J, { type: "target", position: j.Left, className: "pbu-handle", isConnectable: !1 }),
557
- /* @__PURE__ */ u("div", { className: "pbu-node-header", children: [
558
- /* @__PURE__ */ n("span", { className: "pbu-node-title", children: o.title }),
559
- /* @__PURE__ */ n("span", { className: "pbu-node-path", children: o.external ? "외부 ↗" : o.path })
593
+ /* @__PURE__ */ e(Q, { type: "target", position: V.Left, className: "pbu-handle", isConnectable: !1 }),
594
+ /* @__PURE__ */ a("div", { className: "pbu-node-header", children: [
595
+ /* @__PURE__ */ e("span", { className: "pbu-node-title", children: n.title }),
596
+ /* @__PURE__ */ e("span", { className: "pbu-node-path", children: n.external ? "외부 ↗" : n.path })
560
597
  ] }),
561
- /* @__PURE__ */ u("div", { className: "pbu-node-body", style: { height: c }, children: [
562
- o.external ? /* @__PURE__ */ n("div", { className: "pbu-node-placeholder", children: "↗ 외부 링크" }) : p ? /* @__PURE__ */ n(
598
+ /* @__PURE__ */ a("div", { className: "pbu-node-body", style: { height: s }, children: [
599
+ n.external ? /* @__PURE__ */ e("div", { className: "pbu-node-placeholder", children: "↗ 외부 링크" }) : f ? /* @__PURE__ */ e(
563
600
  "iframe",
564
601
  {
565
602
  className: "pbu-node-iframe",
566
- src: o.path,
567
- title: `${o.title} 미리보기`,
603
+ src: n.path,
604
+ title: `${n.title} 미리보기`,
568
605
  loading: "lazy",
569
606
  tabIndex: -1,
570
607
  style: {
571
608
  width: r.width,
572
609
  height: r.height,
573
- transform: `scale(${x})`
610
+ transform: `scale(${p})`
574
611
  }
575
612
  }
576
- ) : /* @__PURE__ */ n("div", { className: "pbu-node-placeholder", children: "…" }),
577
- /* @__PURE__ */ n("div", { className: "pbu-node-shield" })
613
+ ) : /* @__PURE__ */ e("div", { className: "pbu-node-placeholder", children: "…" }),
614
+ /* @__PURE__ */ e("div", { className: "pbu-node-shield" })
578
615
  ] }),
579
- /* @__PURE__ */ n(J, { type: "source", position: j.Right, className: "pbu-handle", isConnectable: !1 })
616
+ /* @__PURE__ */ e(Q, { type: "source", position: V.Right, className: "pbu-handle", isConnectable: !1 })
580
617
  ] });
581
- }), Ee = { page: Ne }, V = 260, ze = 30;
582
- function Se({ ia: e }) {
583
- const t = y((c) => c.closeMap), o = y((c) => c.toggleSkillDrawer), { nodes: r, edges: a } = G(() => {
584
- const c = V / e.viewport.width, i = Math.round(e.viewport.height * c), l = i + ze, p = _e(e.nodes, V, l), s = p.map((f) => ({
585
- id: f.id,
618
+ }), ze = { page: Ne }, Y = 260, Ce = 30;
619
+ function Ee({ ia: t }) {
620
+ const o = k((l) => l.closeMap), { nodes: n, edges: r } = K(() => {
621
+ const l = Y / t.viewport.width, s = Math.round(t.viewport.height * l), c = s + Ce, i = _e(t.nodes, Y, c), f = i.map((p) => ({
622
+ id: p.id,
586
623
  type: "page",
587
- position: { x: f.x, y: f.y },
624
+ position: { x: p.x, y: p.y },
588
625
  data: {
589
- page: f,
590
- viewport: e.viewport,
591
- thumbWidth: V,
592
- bodyHeight: i
626
+ page: p,
627
+ viewport: t.viewport,
628
+ thumbWidth: Y,
629
+ bodyHeight: s
593
630
  },
594
- sourcePosition: j.Right,
595
- targetPosition: j.Left
596
- })), x = p.filter((f) => f.parentId).map((f) => ({
597
- id: `${f.parentId}->${f.id}`,
598
- source: f.parentId,
599
- target: f.id,
631
+ sourcePosition: V.Right,
632
+ targetPosition: V.Left
633
+ })), g = i.filter((p) => p.parentId).map((p) => ({
634
+ id: `${p.parentId}->${p.id}`,
635
+ source: p.parentId,
636
+ target: p.id,
600
637
  type: "smoothstep"
601
638
  }));
602
- return { nodes: s, edges: x };
603
- }, [e]);
604
- return I(() => {
605
- const c = (i) => {
606
- if (i.key !== "Escape") return;
607
- const l = y.getState();
608
- l.viewerPath || l.skillDrawerOpen || t();
639
+ return { nodes: f, edges: g };
640
+ }, [t]);
641
+ return A(() => {
642
+ const l = (s) => {
643
+ if (s.key !== "Escape") return;
644
+ const c = k.getState();
645
+ c.viewerPath || c.skillDrawerOpen || o();
609
646
  };
610
- return window.addEventListener("keydown", c), () => window.removeEventListener("keydown", c);
611
- }, [t]), /* @__PURE__ */ u("div", { className: "pbu-overlay", children: [
612
- /* @__PURE__ */ u("div", { className: "pbu-bar", children: [
613
- /* @__PURE__ */ n("span", { className: "pbu-logo", children: "pubuilder" }),
614
- /* @__PURE__ */ n("span", { className: "pbu-hint", children: "노드 클릭 → 페이지 확대 · 스크롤 줌 · 드래그 팬 · Esc 닫기" }),
615
- /* @__PURE__ */ n("span", { className: "pbu-spacer" }),
616
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-btn", onClick: o, children: "🧰 스킬함" }),
617
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-icon-btn", onClick: t, "aria-label": "닫기", children: "✕" })
647
+ return window.addEventListener("keydown", l), () => window.removeEventListener("keydown", l);
648
+ }, [o]), /* @__PURE__ */ a("div", { className: "pbu-overlay", children: [
649
+ /* @__PURE__ */ a("div", { className: "pbu-bar", children: [
650
+ /* @__PURE__ */ e("span", { className: "pbu-logo", children: "pubuilder" }),
651
+ /* @__PURE__ */ e("span", { className: "pbu-hint", children: "노드 클릭 → 페이지 확대 · 스크롤 줌 · 드래그 팬 · Esc 닫기" }),
652
+ /* @__PURE__ */ e("span", { className: "pbu-spacer" }),
653
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-icon-btn", onClick: o, "aria-label": "닫기", children: "✕" })
618
654
  ] }),
619
- /* @__PURE__ */ n("div", { className: "pbu-canvas", children: /* @__PURE__ */ n(
620
- pe,
655
+ /* @__PURE__ */ e("div", { className: "pbu-canvas", children: /* @__PURE__ */ e(
656
+ he,
621
657
  {
622
- nodes: r,
623
- edges: a,
624
- nodeTypes: Ee,
658
+ nodes: n,
659
+ edges: r,
660
+ nodeTypes: ze,
625
661
  fitView: !0,
626
662
  fitViewOptions: { padding: 0.15, maxZoom: 1 },
627
663
  minZoom: 0.05,
@@ -633,20 +669,20 @@ function Se({ ia: e }) {
633
669
  ) })
634
670
  ] });
635
671
  }
636
- function Ce() {
637
- const e = y((r) => r.isMapOpen), t = y((r) => r.openMap), o = y((r) => r.closeMap);
638
- return /* @__PURE__ */ n(
672
+ function Se() {
673
+ const t = k((r) => r.isMapOpen), o = k((r) => r.openMap), n = k((r) => r.closeMap);
674
+ return /* @__PURE__ */ e(
639
675
  "button",
640
676
  {
641
677
  type: "button",
642
678
  className: "pbu-fab",
643
679
  title: "Page Map (pubuilder)",
644
680
  "aria-label": "페이지 맵 열기",
645
- onClick: () => e ? o() : t(),
646
- children: /* @__PURE__ */ u("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
647
- /* @__PURE__ */ n("polygon", { points: "3 6 9 3 15 6 21 3 21 18 15 21 9 18 3 21" }),
648
- /* @__PURE__ */ n("line", { x1: "9", y1: "3", x2: "9", y2: "18" }),
649
- /* @__PURE__ */ n("line", { x1: "15", y1: "6", x2: "15", y2: "21" })
681
+ onClick: () => t ? n() : o(),
682
+ children: /* @__PURE__ */ a("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
683
+ /* @__PURE__ */ e("polygon", { points: "3 6 9 3 15 6 21 3 21 18 15 21 9 18 3 21" }),
684
+ /* @__PURE__ */ e("line", { x1: "9", y1: "3", x2: "9", y2: "18" }),
685
+ /* @__PURE__ */ e("line", { x1: "15", y1: "6", x2: "15", y2: "21" })
650
686
  ] })
651
687
  }
652
688
  );
@@ -660,7 +696,7 @@ const Te = /* @__PURE__ */ new Set([
660
696
  "article",
661
697
  "aside",
662
698
  "form"
663
- ]), Le = /* @__PURE__ */ new Set([
699
+ ]), Me = /* @__PURE__ */ new Set([
664
700
  "a",
665
701
  "button",
666
702
  "input",
@@ -680,210 +716,210 @@ const Te = /* @__PURE__ */ new Set([
680
716
  "p",
681
717
  "label"
682
718
  ]);
683
- function le(e, t) {
684
- const o = [];
685
- let r = e;
686
- for (; r && r !== t.body && r !== t.documentElement; )
687
- o.push(r), r = r.parentElement;
688
- return o;
689
- }
690
- function Me(e, t) {
691
- const o = le(e, t);
692
- if (o.length === 0) return null;
693
- const r = o.find((i) => {
694
- const l = i.tagName.toLowerCase();
695
- return Te.has(l) && l !== "main";
719
+ function ce(t, o) {
720
+ const n = [];
721
+ let r = t;
722
+ for (; r && r !== o.body && r !== o.documentElement; )
723
+ n.push(r), r = r.parentElement;
724
+ return n;
725
+ }
726
+ function Le(t, o) {
727
+ const n = ce(t, o);
728
+ if (n.length === 0) return null;
729
+ const r = n.find((c) => {
730
+ const i = c.tagName.toLowerCase();
731
+ return Te.has(i) && i !== "main";
696
732
  });
697
733
  if (r) return r;
698
- const a = o.find((i) => i.tagName.toLowerCase() === "main");
699
- if (a) return a;
700
- const c = t.body.scrollHeight || 1;
701
- for (let i = o.length - 1; i >= 0; i--) {
702
- const l = o[i].getBoundingClientRect();
703
- if (l.height > 0 && l.height < c * 0.8) return o[i];
734
+ const l = n.find((c) => c.tagName.toLowerCase() === "main");
735
+ if (l) return l;
736
+ const s = o.body.scrollHeight || 1;
737
+ for (let c = n.length - 1; c >= 0; c--) {
738
+ const i = n[c].getBoundingClientRect();
739
+ if (i.height > 0 && i.height < s * 0.8) return n[c];
704
740
  }
705
- return o[o.length - 1];
706
- }
707
- function Pe(e, t) {
708
- const o = le(e, t);
709
- for (const r of o) {
710
- if (Le.has(r.tagName.toLowerCase())) return r;
711
- const a = r.getBoundingClientRect(), c = r.children.length > 0 || (r.textContent ?? "").trim().length > 0;
712
- if (a.width >= 40 && a.height >= 24 && c) return r;
741
+ return n[n.length - 1];
742
+ }
743
+ function Pe(t, o) {
744
+ const n = ce(t, o);
745
+ for (const r of n) {
746
+ if (Me.has(r.tagName.toLowerCase())) return r;
747
+ const l = r.getBoundingClientRect(), s = r.children.length > 0 || (r.textContent ?? "").trim().length > 0;
748
+ if (l.width >= 40 && l.height >= 24 && s) return r;
713
749
  }
714
- return o[0] ?? null;
715
- }
716
- function Oe(e, t, o) {
717
- return o === "all" ? t.body : o === "section" ? Me(e, t) : Pe(e, t);
718
- }
719
- function Ie(e) {
720
- const o = e.querySelector("h1, h2, h3, h4, h5, h6")?.textContent?.trim();
721
- if (o) return B(o);
722
- const r = e.getAttribute("aria-label");
723
- if (r) return B(r);
724
- const a = e.getAttribute("alt");
725
- if (a) return B(a);
726
- const c = (e.textContent ?? "").trim().replace(/\s+/g, " ");
727
- return c ? B(c) : `<${e.tagName.toLowerCase()}>`;
728
- }
729
- function B(e, t = 30) {
730
- return e.length > t ? `${e.slice(0, t)}…` : e;
731
- }
732
- function Re(e, t) {
733
- if (e.id) return `#${CSS.escape(e.id)}`;
734
- const o = [];
735
- let r = e;
736
- for (; r && r !== t.body && o.length < 8; ) {
750
+ return n[0] ?? null;
751
+ }
752
+ function Oe(t, o, n) {
753
+ return n === "all" ? o.body : n === "section" ? Le(t, o) : Pe(t, o);
754
+ }
755
+ function Ie(t) {
756
+ const n = t.querySelector("h1, h2, h3, h4, h5, h6")?.textContent?.trim();
757
+ if (n) return q(n);
758
+ const r = t.getAttribute("aria-label");
759
+ if (r) return q(r);
760
+ const l = t.getAttribute("alt");
761
+ if (l) return q(l);
762
+ const s = (t.textContent ?? "").trim().replace(/\s+/g, " ");
763
+ return s ? q(s) : `<${t.tagName.toLowerCase()}>`;
764
+ }
765
+ function q(t, o = 30) {
766
+ return t.length > o ? `${t.slice(0, o)}…` : t;
767
+ }
768
+ function Re(t, o) {
769
+ if (t.id) return `#${CSS.escape(t.id)}`;
770
+ const n = [];
771
+ let r = t;
772
+ for (; r && r !== o.body && n.length < 8; ) {
737
773
  if (r.id)
738
- return o.unshift(`#${CSS.escape(r.id)}`), o.join(" > ");
739
- const a = r.tagName.toLowerCase(), c = r.parentElement;
740
- let i = a;
741
- if (c) {
742
- const l = Array.from(c.children).filter(
743
- (p) => p.tagName === r.tagName
774
+ return n.unshift(`#${CSS.escape(r.id)}`), n.join(" > ");
775
+ const l = r.tagName.toLowerCase(), s = r.parentElement;
776
+ let c = l;
777
+ if (s) {
778
+ const i = Array.from(s.children).filter(
779
+ (f) => f.tagName === r.tagName
744
780
  );
745
- l.length > 1 && (i += `:nth-of-type(${l.indexOf(r) + 1})`);
781
+ i.length > 1 && (c += `:nth-of-type(${i.indexOf(r) + 1})`);
746
782
  }
747
- o.unshift(i), r = c;
783
+ n.unshift(c), r = s;
748
784
  }
749
- return o.join(" > ");
785
+ return n.join(" > ");
750
786
  }
751
- function Z(e, t, o) {
752
- const r = e.createElement("div");
787
+ function te(t, o, n) {
788
+ const r = t.createElement("div");
753
789
  r.setAttribute("data-pubuilder", "highlight"), Object.assign(r.style, {
754
790
  position: "fixed",
755
791
  top: "0",
756
792
  left: "0",
757
793
  display: "none",
758
- border: `1px solid ${t}`,
759
- background: o,
794
+ border: `1px solid ${o}`,
795
+ background: n,
760
796
  borderRadius: "0",
761
797
  pointerEvents: "none",
762
798
  zIndex: "2147483647",
763
799
  boxSizing: "border-box"
764
800
  });
765
- const a = e.createElement("div");
766
- return Object.assign(a.style, {
801
+ const l = t.createElement("div");
802
+ return Object.assign(l.style, {
767
803
  position: "absolute",
768
804
  left: "-1px",
769
805
  top: "-22px",
770
806
  padding: "2px 7px",
771
- background: t,
807
+ background: o,
772
808
  color: "#fff",
773
809
  font: "600 10px/16px system-ui, sans-serif",
774
810
  borderRadius: "0",
775
811
  whiteSpace: "nowrap",
776
812
  pointerEvents: "none"
777
- }), r.appendChild(a), { root: r, label: a };
813
+ }), r.appendChild(l), { root: r, label: l };
778
814
  }
779
- function Q(e, t, o, r) {
780
- const a = t.getBoundingClientRect(), c = r ?? -1 / 0, i = Math.max(a.top, c), l = a.bottom - i;
781
- if (l <= 2) {
782
- W(e);
815
+ function oe(t, o, n, r) {
816
+ const l = o.getBoundingClientRect(), s = r ?? -1 / 0, c = Math.max(l.top, s), i = l.bottom - c;
817
+ if (i <= 2) {
818
+ X(t);
783
819
  return;
784
820
  }
785
- e.root.style.display = "block", e.root.style.transform = `translate(${a.x}px, ${i}px)`, e.root.style.width = `${a.width}px`, e.root.style.height = `${l}px`, e.label.textContent = o, e.label.style.top = i < 30 || i - 24 < c ? "2px" : "-24px";
821
+ t.root.style.display = "block", t.root.style.transform = `translate(${l.x}px, ${c}px)`, t.root.style.width = `${l.width}px`, t.root.style.height = `${i}px`, t.label.textContent = n, t.label.style.top = c < 30 || c - 24 < s ? "2px" : "-24px";
786
822
  }
787
- function W(e) {
788
- e.root.style.display = "none";
823
+ function X(t) {
824
+ t.root.style.display = "none";
789
825
  }
790
- function ee(e) {
791
- const t = e.getBoundingClientRect();
792
- return `${e.tagName.toLowerCase()} · ${Math.round(t.width)}×${Math.round(t.height)}`;
826
+ function re(t) {
827
+ const o = t.getBoundingClientRect();
828
+ return `${t.tagName.toLowerCase()} · ${Math.round(o.width)}×${Math.round(o.height)}`;
793
829
  }
794
- function $e(e, t) {
795
- let o = null;
830
+ function $e(t, o) {
831
+ let n = null;
796
832
  try {
797
- o = e.contentDocument;
833
+ n = t.contentDocument;
798
834
  } catch {
799
835
  return null;
800
836
  }
801
- const r = e.contentWindow;
802
- if (!o || !o.body || !r) return null;
803
- const a = o;
804
- let c = t.granularity, i = t.enabled, l = null, p = null;
805
- const s = Z(a, "rgba(14,99,156,0.95)", "rgba(14,99,156,0.10)"), x = Z(a, "rgba(35,134,54,0.95)", "rgba(35,134,54,0.07)");
806
- a.body.appendChild(s.root), a.body.appendChild(x.root);
807
- let f = [], v = 0;
808
- const N = () => {
809
- f = [];
810
- for (const b of Array.from(a.body.querySelectorAll("*"))) {
811
- if (b === s.root || b === x.root || s.root.contains(b) || x.root.contains(b)) continue;
812
- const k = r.getComputedStyle(b).position;
813
- if (k !== "fixed" && k !== "sticky") continue;
814
- const m = b.getBoundingClientRect();
815
- m.width === 0 || m.height === 0 || m.top <= 1 && m.height < r.innerHeight * 0.5 && f.push({ el: b, rect: m });
837
+ const r = t.contentWindow;
838
+ if (!n || !n.body || !r) return null;
839
+ const l = n;
840
+ let s = o.granularity, c = o.enabled, i = null, f = null;
841
+ const g = te(l, "rgba(14,99,156,0.95)", "rgba(14,99,156,0.10)"), p = te(l, "rgba(35,134,54,0.95)", "rgba(35,134,54,0.07)");
842
+ l.body.appendChild(g.root), l.body.appendChild(p.root);
843
+ let m = [], _ = 0;
844
+ const d = () => {
845
+ m = [];
846
+ for (const b of Array.from(l.body.querySelectorAll("*"))) {
847
+ if (b === g.root || b === p.root || g.root.contains(b) || p.root.contains(b)) continue;
848
+ const y = r.getComputedStyle(b).position;
849
+ if (y !== "fixed" && y !== "sticky") continue;
850
+ const w = b.getBoundingClientRect();
851
+ w.width === 0 || w.height === 0 || w.top <= 1 && w.height < r.innerHeight * 0.5 && m.push({ el: b, rect: w });
816
852
  }
817
- }, g = () => {
818
- const b = Date.now();
819
- b - v < 500 || (v = b, N());
820
- }, S = (b) => {
821
- const k = b.getBoundingClientRect();
822
- let m = null;
823
- for (const E of f)
824
- E.el === b || E.el.contains(b) || b.contains(E.el) || !(k.left < E.rect.right && k.right > E.rect.left) || (m === null || E.rect.bottom > m) && (m = E.rect.bottom);
825
- return m;
826
853
  }, C = () => {
827
- l && i && l.isConnected ? Q(s, l, ee(l), S(l)) : W(s), p && p.isConnected ? Q(x, p, `선택됨 · ${ee(p)}`, S(p)) : W(x);
828
- }, L = (b) => {
829
- if (c === "all") return a.body;
830
- if (p && p.isConnected && p.contains(b)) {
831
- if (p === b) return p;
832
- let k = b;
833
- for (; k.parentElement && k.parentElement !== p; )
834
- k = k.parentElement;
835
- return k;
854
+ const b = Date.now();
855
+ b - _ < 500 || (_ = b, d());
856
+ }, E = (b) => {
857
+ const y = b.getBoundingClientRect();
858
+ let w = null;
859
+ for (const S of m)
860
+ S.el === b || S.el.contains(b) || b.contains(S.el) || !(y.left < S.rect.right && y.right > S.rect.left) || (w === null || S.rect.bottom > w) && (w = S.rect.bottom);
861
+ return w;
862
+ }, P = () => {
863
+ i && c && i.isConnected ? oe(g, i, re(i), E(i)) : X(g), f && f.isConnected ? oe(p, f, `선택됨 · ${re(f)}`, E(f)) : X(p);
864
+ }, T = (b) => {
865
+ if (s === "all") return l.body;
866
+ if (f && f.isConnected && f.contains(b)) {
867
+ if (f === b) return f;
868
+ let y = b;
869
+ for (; y.parentElement && y.parentElement !== f; )
870
+ y = y.parentElement;
871
+ return y;
836
872
  }
837
- return Oe(b, a, c);
838
- }, R = (b) => {
839
- if (!i) return;
840
- g();
841
- const k = b.target;
842
- if (!k || !a.body.contains(k)) return;
843
- const m = L(k);
844
- m !== l && (l = m, C());
845
- }, M = (b) => {
846
- if (!i) return;
847
- b.preventDefault(), b.stopPropagation(), N(), v = Date.now();
848
- const k = b.target;
849
- if (!k) return;
850
- const m = L(k);
851
- if (!m) return;
852
- p = m, C();
853
- const E = m.getBoundingClientRect();
854
- t.onSelect(
873
+ return Oe(b, l, s);
874
+ }, j = (b) => {
875
+ if (!c) return;
876
+ C();
877
+ const y = b.target;
878
+ if (!y || !l.body.contains(y)) return;
879
+ const w = T(y);
880
+ w !== i && (i = w, P());
881
+ }, O = (b) => {
882
+ if (!c) return;
883
+ b.preventDefault(), b.stopPropagation(), d(), _ = Date.now();
884
+ const y = b.target;
885
+ if (!y) return;
886
+ const w = T(y);
887
+ if (!w) return;
888
+ f = w, P();
889
+ const S = w.getBoundingClientRect();
890
+ o.onSelect(
855
891
  {
856
- pagePath: t.pagePath,
857
- selector: Re(m, a),
858
- tag: m.tagName.toLowerCase(),
859
- label: Ie(m),
892
+ pagePath: o.pagePath,
893
+ selector: Re(w, l),
894
+ tag: w.tagName.toLowerCase(),
895
+ label: Ie(w),
860
896
  rect: {
861
- x: E.x + r.scrollX,
862
- y: E.y + r.scrollY,
863
- width: E.width,
864
- height: E.height
897
+ x: S.x + r.scrollX,
898
+ y: S.y + r.scrollY,
899
+ width: S.width,
900
+ height: S.height
865
901
  },
866
- granularity: c
902
+ granularity: s
867
903
  },
868
- m
904
+ w
869
905
  );
870
- }, T = () => {
871
- l = null, C();
872
- }, O = () => C(), P = () => {
873
- N(), C();
906
+ }, M = () => {
907
+ i = null, P();
908
+ }, $ = () => P(), I = () => {
909
+ d(), P();
874
910
  };
875
- return N(), a.addEventListener("mousemove", R, !0), a.addEventListener("click", M, !0), a.documentElement.addEventListener("mouseleave", T), r.addEventListener("scroll", O, !0), r.addEventListener("resize", P), {
911
+ return d(), l.addEventListener("mousemove", j, !0), l.addEventListener("click", O, !0), l.documentElement.addEventListener("mouseleave", M), r.addEventListener("scroll", $, !0), r.addEventListener("resize", I), {
876
912
  destroy() {
877
913
  try {
878
- a.removeEventListener("mousemove", R, !0), a.removeEventListener("click", M, !0), a.documentElement.removeEventListener("mouseleave", T), r.removeEventListener("scroll", O, !0), r.removeEventListener("resize", P), s.root.remove(), x.root.remove();
914
+ l.removeEventListener("mousemove", j, !0), l.removeEventListener("click", O, !0), l.documentElement.removeEventListener("mouseleave", M), r.removeEventListener("scroll", $, !0), r.removeEventListener("resize", I), g.root.remove(), p.root.remove();
879
915
  } catch {
880
916
  }
881
917
  },
882
918
  setGranularity(b) {
883
- c = b, l = null, C();
919
+ s = b, i = null, P();
884
920
  },
885
921
  setEnabled(b) {
886
- i = b, b || (l = null), C();
922
+ c = b, b || (i = null), P();
887
923
  }
888
924
  };
889
925
  }
@@ -894,426 +930,510 @@ const De = {
894
930
  done: "✅"
895
931
  };
896
932
  function Ae() {
897
- const e = oe(Y), t = y((d) => d.selection), o = y((d) => d.selectedOuterHTML), r = y((d) => d.toggleSkillDrawer), [a, c] = _(""), [i, l] = _("idle"), [p, s] = _(null), [x, f] = _([]), [v, N] = _(!1), [g, S] = _(!1), [C, L] = _(null), [R, M] = _(null), [T, O] = _(!1), [P, b] = _(!1), k = $(null), m = $(null), E = $(0);
898
- I(() => {
899
- E.current++, m.current?.(), m.current = null, l("idle"), s(null), f([]), N(!1), S(!1), O(!1), L(null), M(null), c("");
900
- }, [t?.selector]), I(() => {
901
- const d = k.current;
902
- d && (d.scrollTop = d.scrollHeight);
903
- }, [x]), I(() => () => {
904
- E.current++, m.current?.(), m.current = null;
933
+ const t = le(Z), o = k((u) => u.selection), n = k((u) => u.selectedOuterHTML), r = k((u) => u.toggleSkillDrawer), [l, s] = v(""), [c, i] = v("idle"), [f, g] = v(null), [p, m] = v([]), [_, d] = v(!1), [C, E] = v(!1), [P, T] = v(null), [j, O] = v(null), [M, $] = v(!1), [I, b] = v(!1), [y, w] = v(""), S = H(null), R = H(null), D = H(0);
934
+ A(() => {
935
+ D.current++, R.current?.(), R.current = null, i("idle"), g(null), m([]), d(!1), E(!1), $(!1), T(null), O(null), s(""), w("");
936
+ }, [o?.selector]), A(() => {
937
+ const u = S.current;
938
+ u && (u.scrollTop = u.scrollHeight);
939
+ }, [p]), A(() => () => {
940
+ D.current++, R.current?.(), R.current = null;
905
941
  }, []);
906
- const A = (d) => {
907
- m.current = e.subscribePublish(d, (z) => {
908
- f((D) => [...D, z]), z.type === "done" ? (l("done"), s(null), O(!1), m.current?.(), m.current = null) : z.type === "error" && (l("error"), L(z.text), s(null), O(!1), m.current?.(), m.current = null);
942
+ const F = (u) => {
943
+ R.current = t.subscribePublish(u, (z) => {
944
+ m((L) => [...L, z]), z.type === "done" ? (i("done"), g(null), $(!1), R.current?.(), R.current = null) : z.type === "error" && (i("error"), T(z.text), g(null), $(!1), R.current?.(), R.current = null);
909
945
  });
910
- }, U = async () => {
911
- if (!t || i === "running" || g) return;
912
- const d = E.current;
913
- N(!1), L(null), M(null), S(!0);
946
+ }, W = async () => {
947
+ if (!o || c === "running" || C) return;
948
+ const u = D.current;
949
+ d(!1), T(null), O(null), E(!0);
914
950
  try {
915
- const z = await e.isAlive();
916
- if (d !== E.current) return;
951
+ const z = await t.isAlive();
952
+ if (u !== D.current) return;
917
953
  if (!z) {
918
- N(!0);
954
+ d(!0);
919
955
  return;
920
956
  }
921
- const { jobId: D } = await e.startPublish({
922
- selection: t,
923
- outerHTML: o ?? "",
924
- figmaUrl: a
957
+ const { jobId: L } = await t.startPublish({
958
+ selection: o,
959
+ outerHTML: n ?? "",
960
+ figmaUrl: l
925
961
  });
926
- if (d !== E.current) {
927
- e.cancelPublish(D).catch(() => {
962
+ if (u !== D.current) {
963
+ t.cancelPublish(L).catch(() => {
928
964
  });
929
965
  return;
930
966
  }
931
- s(D), f([]), l("running"), A(D);
967
+ g(L), m([]), i("running"), F(L);
932
968
  } catch (z) {
933
- if (d !== E.current) return;
934
- l("error"), L(z instanceof Error ? z.message : String(z)), M(z instanceof re ? z.code ?? null : null);
969
+ if (u !== D.current) return;
970
+ i("error"), T(z instanceof Error ? z.message : String(z)), O(z instanceof J ? z.code ?? null : null);
935
971
  } finally {
936
- S(!1);
972
+ E(!1);
937
973
  }
938
- }, F = async () => {
939
- if (!(!p || T)) {
940
- O(!0);
974
+ }, U = async () => {
975
+ if (!(!f || M)) {
976
+ $(!0);
941
977
  try {
942
- await e.cancelPublish(p);
943
- } catch (d) {
944
- L(d instanceof Error ? d.message : String(d)), O(!1);
978
+ await t.cancelPublish(f);
979
+ } catch (u) {
980
+ T(u instanceof Error ? u.message : String(u)), $(!1);
981
+ }
982
+ }
983
+ }, G = async () => {
984
+ const u = y.trim();
985
+ if (!o || !u || C || N) return;
986
+ const z = D.current;
987
+ E(!0), T(null);
988
+ try {
989
+ const { jobId: L } = await t.startPublish({
990
+ selection: o,
991
+ outerHTML: n ?? "",
992
+ figmaUrl: l,
993
+ instruction: u
994
+ });
995
+ if (z !== D.current) {
996
+ t.cancelPublish(L).catch(() => {
997
+ });
998
+ return;
945
999
  }
1000
+ m((ie) => [...ie, { type: "log", text: `내 답변: ${u}` }]), w(""), g(L), i("running"), F(L);
1001
+ } catch (L) {
1002
+ if (z !== D.current) return;
1003
+ i("error"), T(L instanceof Error ? L.message : String(L)), O(L instanceof J ? L.code ?? null : null);
1004
+ } finally {
1005
+ E(!1);
946
1006
  }
947
- }, q = async () => {
1007
+ }, h = async () => {
948
1008
  await navigator.clipboard.writeText("npx pubuilder serve"), b(!0), setTimeout(() => b(!1), 1200);
949
- }, H = async () => {
950
- S(!0);
1009
+ }, x = async () => {
1010
+ E(!0);
951
1011
  try {
952
- const d = await e.isAlive();
953
- N(!d);
1012
+ const u = await t.isAlive();
1013
+ d(!u);
954
1014
  } finally {
955
- S(!1);
1015
+ E(!1);
956
1016
  }
957
- }, h = i === "running";
958
- return /* @__PURE__ */ u("div", { className: "pbu-publish", children: [
959
- /* @__PURE__ */ n("label", { children: "Figma 노드 링크" }),
960
- /* @__PURE__ */ n(
1017
+ }, N = c === "running";
1018
+ return /* @__PURE__ */ a("div", { className: "pbu-publish", children: [
1019
+ /* @__PURE__ */ a("div", { className: "pbu-publish-heading", children: [
1020
+ /* @__PURE__ */ e("label", { htmlFor: "pbu-figma-url", children: "Figma 노드 링크" }),
1021
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-btn pbu-skill-entry", onClick: r, children: "🧰 스킬함 · 설정" })
1022
+ ] }),
1023
+ /* @__PURE__ */ e(
961
1024
  "input",
962
1025
  {
963
- value: a,
964
- onChange: (d) => c(d.target.value),
965
- disabled: h,
1026
+ id: "pbu-figma-url",
1027
+ value: l,
1028
+ onChange: (u) => s(u.target.value),
1029
+ disabled: N,
966
1030
  placeholder: "https://www.figma.com/design/..."
967
1031
  }
968
1032
  ),
969
- v && /* @__PURE__ */ u("div", { className: "pbu-panel-empty", children: [
1033
+ _ && /* @__PURE__ */ a("div", { className: "pbu-panel-empty", children: [
970
1034
  "컴패니언 서버가 꺼져 있어요",
971
- /* @__PURE__ */ u("div", { className: "pbu-drawer-code", children: [
972
- /* @__PURE__ */ n("code", { children: "npx pubuilder serve" }),
973
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-btn", onClick: q, children: P ? "복사됨 ✓" : "복사" })
1035
+ /* @__PURE__ */ a("div", { className: "pbu-drawer-code", children: [
1036
+ /* @__PURE__ */ e("code", { children: "npx pubuilder serve" }),
1037
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-btn", onClick: h, children: I ? "복사됨 ✓" : "복사" })
974
1038
  ] }),
975
- /* @__PURE__ */ n("div", { className: "pbu-hint", children: 'package.json의 dev 스크립트를 "pubuilder dev -- <기존 명령>"으로 감싸면 자동 실행돼요' }),
976
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-btn", disabled: g, onClick: H, children: "다시 확인" })
1039
+ /* @__PURE__ */ e("div", { className: "pbu-hint", children: 'package.json의 dev 스크립트를 "pubuilder dev -- <기존 명령>"으로 감싸면 자동 실행돼요' }),
1040
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-btn", disabled: C, onClick: x, children: "다시 확인" })
977
1041
  ] }),
978
- C && !v && /* @__PURE__ */ u("div", { className: "pbu-drawer-error", children: [
979
- /* @__PURE__ */ n("span", { children: C }),
980
- (R === "NO_FIGMA_TOKEN" || R === "FIGMA_API_ERROR") && /* @__PURE__ */ n("button", { type: "button", className: "pbu-btn", onClick: r, children: "스킬함 열기" })
1042
+ P && !_ && /* @__PURE__ */ a("div", { className: "pbu-drawer-error", children: [
1043
+ /* @__PURE__ */ e("span", { children: P }),
1044
+ (j === "NO_FIGMA_TOKEN" || j === "FIGMA_API_ERROR") && /* @__PURE__ */ e("button", { type: "button", className: "pbu-btn", onClick: r, children: "스킬함 열기" })
981
1045
  ] }),
982
- h ? /* @__PURE__ */ n("button", { type: "button", className: "pbu-btn pbu-btn-primary", disabled: T, onClick: F, children: T ? "중단 중..." : "중단" }) : /* @__PURE__ */ n(
1046
+ N ? /* @__PURE__ */ e("button", { type: "button", className: "pbu-btn pbu-btn-primary", disabled: M, onClick: U, children: M ? "중단 중..." : "중단" }) : /* @__PURE__ */ e(
983
1047
  "button",
984
1048
  {
985
1049
  type: "button",
986
1050
  className: "pbu-btn pbu-btn-primary",
987
- disabled: g || !t,
988
- onClick: U,
1051
+ disabled: C || !o,
1052
+ onClick: W,
989
1053
  children: "이 블록 퍼블리싱"
990
1054
  }
991
1055
  ),
992
- (x.length > 0 || h) && /* @__PURE__ */ u("div", { className: "pbu-publish-log", ref: k, children: [
993
- h && x.length === 0 && /* @__PURE__ */ n("div", { className: "pbu-log-line pbu-log-tool", children: "실행 중..." }),
994
- x.map((d, z) => /* @__PURE__ */ u(
1056
+ (p.length > 0 || N) && /* @__PURE__ */ a("div", { className: "pbu-publish-log", ref: S, children: [
1057
+ N && p.length === 0 && /* @__PURE__ */ e("div", { className: "pbu-log-line pbu-log-tool", children: "실행 중..." }),
1058
+ p.map((u, z) => /* @__PURE__ */ a(
995
1059
  "div",
996
1060
  {
997
- className: d.type === "error" ? "pbu-log-line pbu-log-error" : d.type === "done" ? "pbu-log-line pbu-log-done" : d.type === "tool" ? "pbu-log-line pbu-log-tool" : "pbu-log-line",
1061
+ className: u.type === "error" ? "pbu-log-line pbu-log-error" : u.type === "done" ? "pbu-log-line pbu-log-done" : u.type === "tool" ? "pbu-log-line pbu-log-tool" : "pbu-log-line",
998
1062
  children: [
999
- /* @__PURE__ */ n("span", { children: De[d.type] }),
1063
+ /* @__PURE__ */ e("span", { children: De[u.type] }),
1000
1064
  " ",
1001
- /* @__PURE__ */ n("span", { children: d.text })
1065
+ /* @__PURE__ */ e("span", { children: u.text })
1002
1066
  ]
1003
1067
  },
1004
1068
  z
1005
1069
  ))
1070
+ ] }),
1071
+ c === "done" && /* @__PURE__ */ a("div", { className: "pbu-publish-reply", children: [
1072
+ /* @__PURE__ */ e("label", { htmlFor: "pbu-publish-reply", children: "AI에게 이어서 답하기" }),
1073
+ /* @__PURE__ */ e(
1074
+ "textarea",
1075
+ {
1076
+ id: "pbu-publish-reply",
1077
+ value: y,
1078
+ onChange: (u) => w(u.target.value),
1079
+ onKeyDown: (u) => {
1080
+ (u.metaKey || u.ctrlKey) && u.key === "Enter" && G();
1081
+ },
1082
+ placeholder: "예: B 방향으로 진행해줘. 공지와 알림은 유지해.",
1083
+ rows: 3
1084
+ }
1085
+ ),
1086
+ /* @__PURE__ */ a("div", { className: "pbu-publish-reply-actions", children: [
1087
+ /* @__PURE__ */ e("span", { children: "⌘/Ctrl + Enter" }),
1088
+ /* @__PURE__ */ e(
1089
+ "button",
1090
+ {
1091
+ type: "button",
1092
+ className: "pbu-btn pbu-btn-primary",
1093
+ disabled: C || !y.trim(),
1094
+ onClick: G,
1095
+ children: C ? "전송 중..." : "답변 전송"
1096
+ }
1097
+ )
1098
+ ] })
1006
1099
  ] })
1007
1100
  ] });
1008
1101
  }
1009
- function He() {
1010
- const e = y((a) => a.selection), [t, o] = _(!1), r = async () => {
1011
- e && (await navigator.clipboard.writeText(e.selector), o(!0), setTimeout(() => o(!1), 1200));
1102
+ function je() {
1103
+ const t = k((l) => l.selection), [o, n] = v(!1), r = async () => {
1104
+ t && (await navigator.clipboard.writeText(t.selector), n(!0), setTimeout(() => n(!1), 1200));
1012
1105
  };
1013
- return /* @__PURE__ */ u("aside", { className: "pbu-panel", children: [
1014
- /* @__PURE__ */ n("div", { className: "pbu-panel-title", children: "선택된 블록" }),
1015
- e ? /* @__PURE__ */ u(te, { children: [
1016
- /* @__PURE__ */ u("div", { className: "pbu-field", children: [
1017
- /* @__PURE__ */ n("label", { children: "페이지" }),
1018
- /* @__PURE__ */ n("code", { children: e.pagePath })
1106
+ return /* @__PURE__ */ a("aside", { className: "pbu-panel", children: [
1107
+ /* @__PURE__ */ e("div", { className: "pbu-panel-title", children: "선택된 블록" }),
1108
+ t ? /* @__PURE__ */ a(ne, { children: [
1109
+ /* @__PURE__ */ a("div", { className: "pbu-field", children: [
1110
+ /* @__PURE__ */ e("label", { children: "페이지" }),
1111
+ /* @__PURE__ */ e("code", { children: t.pagePath })
1019
1112
  ] }),
1020
- /* @__PURE__ */ u("div", { className: "pbu-field", children: [
1021
- /* @__PURE__ */ n("label", { children: "블록" }),
1022
- /* @__PURE__ */ u("div", { children: [
1023
- /* @__PURE__ */ n("span", { className: "pbu-chip", children: e.tag }),
1024
- /* @__PURE__ */ n("span", { children: e.label })
1113
+ /* @__PURE__ */ a("div", { className: "pbu-field", children: [
1114
+ /* @__PURE__ */ e("label", { children: "블록" }),
1115
+ /* @__PURE__ */ a("div", { children: [
1116
+ /* @__PURE__ */ e("span", { className: "pbu-chip", children: t.tag }),
1117
+ /* @__PURE__ */ e("span", { children: t.label })
1025
1118
  ] })
1026
1119
  ] }),
1027
- /* @__PURE__ */ u("div", { className: "pbu-field", children: [
1028
- /* @__PURE__ */ n("label", { children: "Selector" }),
1029
- /* @__PURE__ */ n("code", { className: "pbu-selector", children: e.selector }),
1030
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-btn", onClick: r, children: t ? "복사됨 ✓" : "Selector 복사" })
1120
+ /* @__PURE__ */ a("div", { className: "pbu-field", children: [
1121
+ /* @__PURE__ */ e("label", { children: "Selector" }),
1122
+ /* @__PURE__ */ e("code", { className: "pbu-selector", children: t.selector }),
1123
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-btn", onClick: r, children: o ? "복사됨 ✓" : "Selector 복사" })
1031
1124
  ] }),
1032
- /* @__PURE__ */ u("div", { className: "pbu-field", children: [
1033
- /* @__PURE__ */ n("label", { children: "크기" }),
1034
- /* @__PURE__ */ u("span", { children: [
1035
- Math.round(e.rect.width),
1125
+ /* @__PURE__ */ a("div", { className: "pbu-field", children: [
1126
+ /* @__PURE__ */ e("label", { children: "크기" }),
1127
+ /* @__PURE__ */ a("span", { children: [
1128
+ Math.round(t.rect.width),
1036
1129
  " × ",
1037
- Math.round(e.rect.height),
1130
+ Math.round(t.rect.height),
1038
1131
  "px"
1039
1132
  ] })
1040
1133
  ] }),
1041
- /* @__PURE__ */ u("div", { className: "pbu-field", children: [
1042
- /* @__PURE__ */ n("label", { children: "단위" }),
1043
- /* @__PURE__ */ n("span", { children: e.granularity === "all" ? "전체" : e.granularity === "section" ? "섹션" : "유닛" })
1134
+ /* @__PURE__ */ a("div", { className: "pbu-field", children: [
1135
+ /* @__PURE__ */ e("label", { children: "단위" }),
1136
+ /* @__PURE__ */ e("span", { children: t.granularity === "all" ? "전체" : t.granularity === "section" ? "섹션" : "유닛" })
1044
1137
  ] }),
1045
- /* @__PURE__ */ n(Ae, {})
1046
- ] }) : /* @__PURE__ */ u("div", { className: "pbu-panel-empty", children: [
1138
+ /* @__PURE__ */ e(Ae, {})
1139
+ ] }) : /* @__PURE__ */ a("div", { className: "pbu-panel-empty", children: [
1047
1140
  "화면에서 블록에 마우스를 올리고 클릭해 선택하세요.",
1048
- /* @__PURE__ */ n("br", {}),
1141
+ /* @__PURE__ */ e("br", {}),
1049
1142
  "상단 토글로 ",
1050
- /* @__PURE__ */ n("b", { children: "전체 / 섹션 / 유닛" }),
1143
+ /* @__PURE__ */ e("b", { children: "전체 / 섹션 / 유닛" }),
1051
1144
  " 단위를 바꿀 수 있어요."
1052
1145
  ] })
1053
1146
  ] });
1054
1147
  }
1055
- function Be({ ia: e }) {
1056
- const t = y((g) => g.viewerPath), o = y((g) => g.closeViewer), r = y((g) => g.granularity), a = y((g) => g.setGranularity), c = y((g) => g.inspectEnabled), i = y((g) => g.setInspectEnabled), l = y((g) => g.toggleSkillDrawer), p = $(null), s = $(null), [x, f] = _(!1), v = e.nodes.find((g) => g.path === t), N = () => {
1057
- s.current?.destroy(), s.current = null;
1058
- const g = p.current;
1059
- if (!g || !t) return;
1060
- const S = y.getState(), C = $e(g, {
1061
- pagePath: t,
1062
- granularity: S.granularity,
1063
- enabled: S.inspectEnabled,
1064
- onSelect: (L, R) => (
1148
+ function He({ ia: t }) {
1149
+ const o = k((d) => d.viewerPath), n = k((d) => d.closeViewer), r = k((d) => d.granularity), l = k((d) => d.setGranularity), s = k((d) => d.inspectEnabled), c = k((d) => d.setInspectEnabled), i = H(null), f = H(null), [g, p] = v(!1), m = t.nodes.find((d) => d.path === o), _ = () => {
1150
+ f.current?.destroy(), f.current = null;
1151
+ const d = i.current;
1152
+ if (!d || !o) return;
1153
+ const C = k.getState(), E = $e(d, {
1154
+ pagePath: o,
1155
+ granularity: C.granularity,
1156
+ enabled: C.inspectEnabled,
1157
+ onSelect: (P, T) => (
1065
1158
  // 20K 상한 — 프롬프트 비대화 방지
1066
- y.getState().setSelectionWithHTML(L, R.outerHTML.slice(0, 2e4))
1159
+ k.getState().setSelectionWithHTML(P, T.outerHTML.slice(0, 2e4))
1067
1160
  )
1068
1161
  });
1069
- if (!C) {
1070
- f(!0);
1162
+ if (!E) {
1163
+ p(!0);
1071
1164
  return;
1072
1165
  }
1073
- f(!1), s.current = C;
1166
+ p(!1), f.current = E;
1074
1167
  };
1075
- return I(() => () => s.current?.destroy(), []), I(() => {
1076
- s.current?.setGranularity(r);
1077
- }, [r]), I(() => {
1078
- s.current?.setEnabled(c);
1079
- }, [c]), I(() => {
1080
- const g = (S) => {
1081
- S.key === "Escape" && (y.getState().skillDrawerOpen || o());
1168
+ return A(() => () => f.current?.destroy(), []), A(() => {
1169
+ f.current?.setGranularity(r);
1170
+ }, [r]), A(() => {
1171
+ f.current?.setEnabled(s);
1172
+ }, [s]), A(() => {
1173
+ const d = (C) => {
1174
+ C.key === "Escape" && (k.getState().skillDrawerOpen || n());
1082
1175
  };
1083
- return window.addEventListener("keydown", g), () => window.removeEventListener("keydown", g);
1084
- }, [o]), v ? /* @__PURE__ */ u("div", { className: "pbu-viewer", children: [
1085
- /* @__PURE__ */ u("div", { className: "pbu-bar", children: [
1086
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-btn", onClick: o, children: "← 맵으로" }),
1087
- /* @__PURE__ */ u("span", { className: "pbu-viewer-title", children: [
1088
- v.title,
1089
- /* @__PURE__ */ n("code", { children: v.path })
1176
+ return window.addEventListener("keydown", d), () => window.removeEventListener("keydown", d);
1177
+ }, [n]), m ? /* @__PURE__ */ a("div", { className: "pbu-viewer", children: [
1178
+ /* @__PURE__ */ a("div", { className: "pbu-bar", children: [
1179
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-btn", onClick: n, children: "← 맵으로" }),
1180
+ /* @__PURE__ */ a("span", { className: "pbu-viewer-title", children: [
1181
+ m.title,
1182
+ /* @__PURE__ */ e("code", { children: m.path })
1090
1183
  ] }),
1091
- /* @__PURE__ */ n("span", { className: "pbu-spacer" }),
1092
- x && /* @__PURE__ */ n("span", { className: "pbu-hint", children: "⚠ 이 페이지는 검사할 수 없어요" }),
1093
- /* @__PURE__ */ u("div", { className: "pbu-seg", role: "group", "aria-label": "블록 단위", children: [
1094
- /* @__PURE__ */ n(
1184
+ /* @__PURE__ */ e("span", { className: "pbu-spacer" }),
1185
+ g && /* @__PURE__ */ e("span", { className: "pbu-hint", children: "⚠ 이 페이지는 검사할 수 없어요" }),
1186
+ /* @__PURE__ */ a("div", { className: "pbu-seg", role: "group", "aria-label": "블록 단위", children: [
1187
+ /* @__PURE__ */ e(
1095
1188
  "button",
1096
1189
  {
1097
1190
  type: "button",
1098
1191
  className: r === "all" ? "pbu-on" : "",
1099
- onClick: () => a("all"),
1192
+ onClick: () => l("all"),
1100
1193
  children: "전체"
1101
1194
  }
1102
1195
  ),
1103
- /* @__PURE__ */ n(
1196
+ /* @__PURE__ */ e(
1104
1197
  "button",
1105
1198
  {
1106
1199
  type: "button",
1107
1200
  className: r === "section" ? "pbu-on" : "",
1108
- onClick: () => a("section"),
1201
+ onClick: () => l("section"),
1109
1202
  children: "섹션"
1110
1203
  }
1111
1204
  ),
1112
- /* @__PURE__ */ n(
1205
+ /* @__PURE__ */ e(
1113
1206
  "button",
1114
1207
  {
1115
1208
  type: "button",
1116
1209
  className: r === "unit" ? "pbu-on" : "",
1117
- onClick: () => a("unit"),
1210
+ onClick: () => l("unit"),
1118
1211
  children: "유닛"
1119
1212
  }
1120
1213
  )
1121
1214
  ] }),
1122
- /* @__PURE__ */ u("label", { className: "pbu-toggle", children: [
1123
- /* @__PURE__ */ n(
1215
+ /* @__PURE__ */ a("label", { className: "pbu-toggle", children: [
1216
+ /* @__PURE__ */ e(
1124
1217
  "input",
1125
1218
  {
1126
1219
  type: "checkbox",
1127
- checked: c,
1128
- onChange: (g) => i(g.target.checked)
1220
+ checked: s,
1221
+ onChange: (d) => c(d.target.checked)
1129
1222
  }
1130
1223
  ),
1131
1224
  "검사 모드"
1132
1225
  ] }),
1133
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-btn", onClick: l, children: "🧰 스킬함" }),
1134
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-icon-btn", onClick: o, "aria-label": "닫기", children: "✕" })
1226
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-icon-btn", onClick: n, "aria-label": "닫기", children: "✕" })
1135
1227
  ] }),
1136
- /* @__PURE__ */ u("div", { className: "pbu-viewer-body", children: [
1137
- /* @__PURE__ */ n("div", { className: "pbu-viewer-frame-wrap", children: /* @__PURE__ */ n(
1228
+ /* @__PURE__ */ a("div", { className: "pbu-viewer-body", children: [
1229
+ /* @__PURE__ */ e("div", { className: "pbu-viewer-frame-wrap", children: /* @__PURE__ */ e(
1138
1230
  "iframe",
1139
1231
  {
1140
- ref: p,
1232
+ ref: i,
1141
1233
  className: "pbu-viewer-iframe",
1142
- src: v.path,
1143
- title: v.title,
1144
- onLoad: N
1234
+ src: m.path,
1235
+ title: m.title,
1236
+ onLoad: _
1145
1237
  }
1146
1238
  ) }),
1147
- /* @__PURE__ */ n(He, {})
1239
+ /* @__PURE__ */ e(je, {})
1148
1240
  ] })
1149
1241
  ] }) : null;
1150
1242
  }
1151
- const je = {
1243
+ const Be = {
1152
1244
  project: "프로젝트",
1153
1245
  global: "글로벌",
1154
1246
  uploaded: "업로드"
1247
+ }, Fe = {
1248
+ project: "현재 프로젝트에서 발견한 스킬 · 여기서는 삭제할 수 없어요",
1249
+ global: "내 전역 환경에 설치된 공용 스킬 · 여기서는 삭제할 수 없어요",
1250
+ uploaded: "이 스킬함에 직접 올린 Markdown 스킬 · 삭제할 수 있어요"
1155
1251
  }, Ue = ["project", "global", "uploaded"];
1156
- function Fe() {
1157
- const e = y((h) => h.toggleSkillDrawer), t = oe(Y), [o, r] = _(!0), [a, c] = _(!1), [i, l] = _([]), [p, s] = _(null), [x, f] = _(""), [v, N] = _(!1), [g, S] = _(null), [C, L] = _(!1), R = $(null), M = $(0), [T, O] = _(null), P = async () => {
1158
- const h = ++M.current;
1159
- r(!0), S(null);
1252
+ function Ge() {
1253
+ const t = k((h) => h.toggleSkillDrawer), o = le(Z), [n, r] = v(!0), [l, s] = v(!1), [c, i] = v([]), [f, g] = v(null), [p, m] = v(""), [_, d] = v(!1), [C, E] = v(null), [P, T] = v(!1), j = H(null), O = H(0), [M, $] = v(null), I = async () => {
1254
+ const h = ++O.current;
1255
+ r(!0), E(null);
1160
1256
  try {
1161
- const w = await t.isAlive();
1162
- if (h !== M.current || (c(w), !w)) return;
1163
- const [d, z] = await Promise.all([t.listSkills(), t.tokenStatus()]);
1164
- if (h !== M.current) return;
1165
- l(d), s(z), N(!z.configured);
1166
- } catch (w) {
1167
- if (h !== M.current) return;
1168
- S(w instanceof Error ? w.message : String(w));
1257
+ const x = await o.isAlive();
1258
+ if (h !== O.current || (s(x), !x)) return;
1259
+ const [N, B] = await Promise.all([o.listSkills(), o.tokenStatus()]);
1260
+ if (h !== O.current) return;
1261
+ i(N), g(B), d(!B.configured);
1262
+ } catch (x) {
1263
+ if (h !== O.current) return;
1264
+ E(x instanceof Error ? x.message : String(x));
1169
1265
  } finally {
1170
- h === M.current && r(!1);
1266
+ h === O.current && r(!1);
1171
1267
  }
1172
1268
  };
1173
- I(() => {
1174
- P();
1175
- }, []), I(() => {
1176
- const h = (w) => {
1177
- w.key === "Escape" && e();
1269
+ A(() => {
1270
+ I();
1271
+ }, []), A(() => {
1272
+ const h = (x) => {
1273
+ x.key === "Escape" && t();
1178
1274
  };
1179
1275
  return window.addEventListener("keydown", h), () => window.removeEventListener("keydown", h);
1180
- }, [e]);
1181
- const b = async (h, w) => {
1182
- if (!T) {
1183
- O(h);
1276
+ }, [t]);
1277
+ const b = async (h, x) => {
1278
+ if (!M) {
1279
+ $(h);
1184
1280
  try {
1185
- await w();
1186
- } catch (d) {
1187
- S(d instanceof Error ? d.message : String(d));
1281
+ await x();
1282
+ } catch (N) {
1283
+ E(N instanceof Error ? N.message : String(N));
1188
1284
  } finally {
1189
- O(null);
1285
+ $(null);
1190
1286
  }
1191
1287
  }
1192
- }, k = (h, w) => b(`toggle:${h}`, async () => {
1193
- await t.toggleSkill(h, w), await P();
1194
- }), m = (h, w) => {
1195
- window.confirm(`"${w}" 스킬을 삭제할까요?`) && b(`remove:${h}`, async () => {
1196
- await t.removeSkill(h), await P();
1288
+ }, y = (h, x) => b(`toggle:${h}`, async () => {
1289
+ await o.toggleSkill(h, x), await I();
1290
+ }), w = (h, x) => {
1291
+ window.confirm(`"${x}" 스킬을 삭제할까요?`) && b(`remove:${h}`, async () => {
1292
+ await o.removeSkill(h), await I();
1197
1293
  });
1198
- }, E = () => R.current?.click(), A = (h) => {
1199
- const w = h.target.files?.[0];
1200
- h.target.value = "", w && b("upload", async () => {
1201
- const d = new FileReader(), z = await new Promise((D, ae) => {
1202
- d.onload = () => D(String(d.result ?? "")), d.onerror = () => ae(d.error ?? new Error("파일을 읽을 수 없어요")), d.readAsText(w);
1294
+ }, S = () => j.current?.click(), R = (h) => {
1295
+ const x = h.target.files?.[0];
1296
+ h.target.value = "", x && b("upload", async () => {
1297
+ const N = new FileReader(), B = await new Promise((u, z) => {
1298
+ N.onload = () => u(String(N.result ?? "")), N.onerror = () => z(N.error ?? new Error("파일을 읽을 수 없어요")), N.readAsText(x);
1203
1299
  });
1204
- await t.uploadSkill(w.name, z), await P();
1300
+ await o.uploadSkill(x.name, B), await I();
1205
1301
  });
1206
- }, U = () => b("token:save", async () => {
1207
- x.trim() && (await t.saveToken(x.trim()), f(""), await P());
1302
+ }, D = () => b("token:save", async () => {
1303
+ p.trim() && (await o.saveToken(p.trim()), m(""), await I());
1208
1304
  }), F = () => b("token:delete", async () => {
1209
- await t.deleteToken(), f(""), await P();
1210
- }), q = async () => {
1211
- await navigator.clipboard.writeText("npx pubuilder serve"), L(!0), setTimeout(() => L(!1), 1200);
1212
- }, H = Ue.map((h) => ({
1305
+ await o.deleteToken(), m(""), await I();
1306
+ }), W = async () => {
1307
+ await navigator.clipboard.writeText("npx pubuilder serve"), T(!0), setTimeout(() => T(!1), 1200);
1308
+ }, U = Ue.map((h) => ({
1213
1309
  source: h,
1214
- label: je[h],
1215
- items: i.filter((w) => w.source === h)
1216
- })).filter((h) => h.items.length > 0);
1217
- return /* @__PURE__ */ u("aside", { className: "pbu-drawer", children: [
1218
- /* @__PURE__ */ u("div", { className: "pbu-drawer-header", children: [
1219
- /* @__PURE__ */ n("span", { className: "pbu-panel-title", children: "스킬함" }),
1220
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-icon-btn", onClick: e, "aria-label": "닫기", children: "" })
1310
+ label: Be[h],
1311
+ items: c.filter((x) => x.source === h)
1312
+ })).filter((h) => h.items.length > 0), G = c.filter((h) => h.enabled).length;
1313
+ return /* @__PURE__ */ a("aside", { className: "pbu-drawer", children: [
1314
+ /* @__PURE__ */ a("div", { className: "pbu-drawer-header", children: [
1315
+ /* @__PURE__ */ a("div", { children: [
1316
+ /* @__PURE__ */ e("span", { className: "pbu-panel-title", children: "스킬함" }),
1317
+ /* @__PURE__ */ e("span", { className: "pbu-drawer-kicker", children: "퍼블리싱 실행 설정" })
1318
+ ] }),
1319
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-icon-btn", onClick: t, "aria-label": "닫기", children: "✕" })
1320
+ ] }),
1321
+ /* @__PURE__ */ a("div", { className: "pbu-drawer-guide", children: [
1322
+ /* @__PURE__ */ e("strong", { children: "다음 퍼블리싱에 적용할 규칙을 고르세요." }),
1323
+ /* @__PURE__ */ e("span", { children: "체크된 스킬의 지침만 AI에게 전달됩니다. 변경 사항은 다음 실행부터 적용돼요." }),
1324
+ !n && l && /* @__PURE__ */ a("div", { className: "pbu-guide-status", children: [
1325
+ /* @__PURE__ */ e("span", { className: "pbu-status-dot pbu-status-dot-on" }),
1326
+ c.length > 0 ? `${G}/${c.length}개 스킬 사용 중` : "사용 가능한 스킬 없음"
1327
+ ] })
1221
1328
  ] }),
1222
- g && /* @__PURE__ */ u("div", { className: "pbu-drawer-error", children: [
1223
- /* @__PURE__ */ n("span", { children: g }),
1224
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-icon-btn", onClick: () => S(null), "aria-label": "닫기", children: "✕" })
1329
+ C && /* @__PURE__ */ a("div", { className: "pbu-drawer-error", children: [
1330
+ /* @__PURE__ */ e("span", { children: C }),
1331
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-icon-btn", onClick: () => E(null), "aria-label": "닫기", children: "✕" })
1225
1332
  ] }),
1226
- o ? /* @__PURE__ */ n("div", { className: "pbu-panel-empty", children: "불러오는 중..." }) : a ? /* @__PURE__ */ u(te, { children: [
1227
- /* @__PURE__ */ n("div", { className: "pbu-drawer-group", children: "토큰" }),
1228
- p?.configured && !v ? /* @__PURE__ */ u("div", { className: "pbu-field", children: [
1229
- /* @__PURE__ */ n("span", { className: "pbu-token-masked", children: p.masked }),
1230
- /* @__PURE__ */ u("div", { children: [
1231
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-btn", disabled: T !== null, onClick: () => N(!0), children: "재입력" }),
1232
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-btn", disabled: T !== null, onClick: F, children: "삭제" })
1333
+ n ? /* @__PURE__ */ e("div", { className: "pbu-panel-empty", children: "불러오는 중..." }) : l ? /* @__PURE__ */ a(ne, { children: [
1334
+ /* @__PURE__ */ a("div", { className: "pbu-drawer-section-head", children: [
1335
+ /* @__PURE__ */ a("div", { children: [
1336
+ /* @__PURE__ */ e("strong", { children: "Figma 연결" }),
1337
+ /* @__PURE__ */ e("span", { children: "노드 링크에서 시안 이미지와 구조 정보를 읽을 때 사용해요." })
1338
+ ] }),
1339
+ /* @__PURE__ */ e("span", { className: `pbu-status-badge ${f?.configured ? "pbu-status-on" : "pbu-status-off"}`, children: f?.configured ? "연결됨" : "연결 필요" })
1340
+ ] }),
1341
+ f?.configured && !_ ? /* @__PURE__ */ a("div", { className: "pbu-field", children: [
1342
+ /* @__PURE__ */ e("span", { className: "pbu-token-masked", children: f.masked }),
1343
+ /* @__PURE__ */ a("div", { children: [
1344
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-btn", disabled: M !== null, onClick: () => d(!0), children: "재입력" }),
1345
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-btn", disabled: M !== null, onClick: F, children: "삭제" })
1233
1346
  ] })
1234
- ] }) : /* @__PURE__ */ u("div", { className: "pbu-field", children: [
1235
- /* @__PURE__ */ n(
1347
+ ] }) : /* @__PURE__ */ a("div", { className: "pbu-field", children: [
1348
+ /* @__PURE__ */ e(
1236
1349
  "input",
1237
1350
  {
1238
1351
  type: "password",
1239
- value: x,
1240
- onChange: (h) => f(h.target.value),
1352
+ value: p,
1353
+ onChange: (h) => m(h.target.value),
1241
1354
  placeholder: "Figma 토큰"
1242
1355
  }
1243
1356
  ),
1244
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-btn pbu-btn-primary", disabled: T !== null, onClick: U, children: "저장" })
1357
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-btn pbu-btn-primary", disabled: M !== null, onClick: D, children: "저장" })
1245
1358
  ] }),
1246
- /* @__PURE__ */ u("div", { className: "pbu-drawer-group", children: [
1247
- "스킬 목록",
1248
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-btn", disabled: T !== null, onClick: E, children: "업로드" }),
1249
- /* @__PURE__ */ n(
1359
+ /* @__PURE__ */ a("div", { className: "pbu-drawer-section-head pbu-drawer-section-head-skills", children: [
1360
+ /* @__PURE__ */ a("div", { children: [
1361
+ /* @__PURE__ */ e("strong", { children: "AI 작업 스킬" }),
1362
+ /* @__PURE__ */ e("span", { children: "스킬은 AI에게 전달되는 작업 규칙이 담긴 Markdown 파일이에요." })
1363
+ ] }),
1364
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-btn", disabled: M !== null, onClick: S, children: "업로드" }),
1365
+ /* @__PURE__ */ e(
1250
1366
  "input",
1251
1367
  {
1252
- ref: R,
1368
+ ref: j,
1253
1369
  type: "file",
1254
1370
  accept: ".md",
1255
1371
  style: { display: "none" },
1256
- onChange: A
1372
+ onChange: R
1257
1373
  }
1258
1374
  )
1259
1375
  ] }),
1260
- H.length === 0 ? /* @__PURE__ */ n("div", { className: "pbu-panel-empty", children: "등록된 스킬이 없어요." }) : H.map((h) => /* @__PURE__ */ u("div", { children: [
1261
- /* @__PURE__ */ n("div", { className: "pbu-drawer-group", children: h.label }),
1262
- h.items.map((w) => /* @__PURE__ */ u("div", { className: "pbu-skill-row", children: [
1263
- /* @__PURE__ */ u("label", { className: "pbu-toggle", children: [
1264
- /* @__PURE__ */ n(
1376
+ U.length === 0 ? /* @__PURE__ */ e("div", { className: "pbu-panel-empty", children: "등록된 스킬이 없어요." }) : U.map((h) => /* @__PURE__ */ a("div", { children: [
1377
+ /* @__PURE__ */ a("div", { className: "pbu-skill-source", children: [
1378
+ /* @__PURE__ */ e("strong", { children: h.label }),
1379
+ /* @__PURE__ */ e("span", { children: Fe[h.source] })
1380
+ ] }),
1381
+ h.items.map((x) => /* @__PURE__ */ a("div", { className: "pbu-skill-row", children: [
1382
+ /* @__PURE__ */ a("label", { className: "pbu-toggle", children: [
1383
+ /* @__PURE__ */ e(
1265
1384
  "input",
1266
1385
  {
1267
1386
  type: "checkbox",
1268
- checked: w.enabled,
1269
- disabled: T !== null,
1270
- onChange: (d) => k(w.id, d.target.checked)
1387
+ checked: x.enabled,
1388
+ disabled: M !== null,
1389
+ onChange: (N) => y(x.id, N.target.checked)
1271
1390
  }
1272
1391
  ),
1273
- w.name
1392
+ x.name
1274
1393
  ] }),
1275
- /* @__PURE__ */ n("span", { className: "pbu-hint", title: w.description, children: w.description }),
1276
- w.source === "uploaded" && /* @__PURE__ */ n(
1394
+ /* @__PURE__ */ e("span", { className: "pbu-hint", title: x.description, children: x.description }),
1395
+ /* @__PURE__ */ e("span", { className: `pbu-skill-state ${x.enabled ? "pbu-skill-state-on" : ""}`, children: M === `toggle:${x.id}` ? "변경 중" : x.enabled ? "사용 중" : "제외됨" }),
1396
+ x.source === "uploaded" && /* @__PURE__ */ e(
1277
1397
  "button",
1278
1398
  {
1279
1399
  type: "button",
1280
1400
  className: "pbu-icon-btn",
1281
- disabled: T !== null,
1282
- onClick: () => m(w.id, w.name),
1401
+ disabled: M !== null,
1402
+ onClick: () => w(x.id, x.name),
1283
1403
  "aria-label": "삭제",
1284
1404
  children: "🗑"
1285
1405
  }
1286
1406
  )
1287
- ] }, w.id))
1407
+ ] }, x.id))
1288
1408
  ] }, h.source))
1289
- ] }) : /* @__PURE__ */ u("div", { className: "pbu-panel-empty", children: [
1409
+ ] }) : /* @__PURE__ */ a("div", { className: "pbu-panel-empty", children: [
1290
1410
  "컴패니언 서버가 꺼져 있어요",
1291
- /* @__PURE__ */ u("div", { className: "pbu-drawer-code", children: [
1292
- /* @__PURE__ */ n("code", { children: "npx pubuilder serve" }),
1293
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-btn", onClick: q, children: C ? "복사됨 ✓" : "복사" })
1411
+ /* @__PURE__ */ a("div", { className: "pbu-drawer-code", children: [
1412
+ /* @__PURE__ */ e("code", { children: "npx pubuilder serve" }),
1413
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-btn", onClick: W, children: P ? "복사됨 ✓" : "복사" })
1294
1414
  ] }),
1295
- /* @__PURE__ */ n("div", { className: "pbu-hint", children: 'package.json의 dev 스크립트를 "pubuilder dev -- <기존 명령>"으로 감싸면 자동 실행돼요' }),
1296
- /* @__PURE__ */ n("button", { type: "button", className: "pbu-btn", onClick: P, children: "다시 확인" })
1415
+ /* @__PURE__ */ e("div", { className: "pbu-hint", children: 'package.json의 dev 스크립트를 "pubuilder dev -- <기존 명령>"으로 감싸면 자동 실행돼요' }),
1416
+ /* @__PURE__ */ e("button", { type: "button", className: "pbu-btn", onClick: I, children: "다시 확인" })
1297
1417
  ] })
1298
1418
  ] });
1299
1419
  }
1300
- function Xe({ config: e, enabled: t = !0, serverUrl: o }) {
1301
- const r = t && !xe(), [a, c] = _(!1), i = y((f) => f.isMapOpen), l = y((f) => f.viewerPath), p = y((f) => f.skillDrawerOpen), s = G(() => ge(e), [e]), x = G(() => new ne(o), [o]);
1302
- return se(() => {
1303
- r && window.self === window.top && (ke(), c(!0));
1304
- }, [r]), !a || !r ? null : de(
1305
- /* @__PURE__ */ u(Y.Provider, { value: x, children: [
1306
- /* @__PURE__ */ n(Ce, {}),
1307
- i && /* @__PURE__ */ n(Se, { ia: s }),
1308
- l && /* @__PURE__ */ n(Be, { ia: s }),
1309
- p && /* @__PURE__ */ n(Fe, {})
1420
+ function Xe({ config: t, enabled: o = !0, serverUrl: n }) {
1421
+ const r = o && !xe(), [l, s] = v(!1), c = k((m) => m.isMapOpen), i = k((m) => m.viewerPath), f = k((m) => m.skillDrawerOpen), g = K(() => be(t), [t]), p = K(() => new ae(n), [n]);
1422
+ return ue(() => {
1423
+ r && window.self === window.top && (ke(), s(!0));
1424
+ }, [r]), !l || !r ? null : pe(
1425
+ /* @__PURE__ */ a(Z.Provider, { value: p, children: [
1426
+ /* @__PURE__ */ e(Se, {}),
1427
+ c && /* @__PURE__ */ e(Ee, { ia: g }),
1428
+ i && /* @__PURE__ */ e(He, { ia: g }),
1429
+ f && /* @__PURE__ */ e(Ge, {})
1310
1430
  ] }),
1311
1431
  document.body
1312
1432
  );
1313
1433
  }
1314
1434
  export {
1315
1435
  Xe as PageMap,
1316
- Je as defineIA,
1317
- ge as normalizeIA
1436
+ et as defineIA,
1437
+ be as normalizeIA
1318
1438
  };
1319
1439
  //# sourceMappingURL=index.js.map