@leviosa-ai/detail-page-editor 0.1.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/components/cardnews/color-input.tsx +380 -0
- package/components/detail-page/ai-generate-panel.tsx +763 -0
- package/components/detail-page/annotation-canvas.tsx +860 -0
- package/components/detail-page/annotation-dialog.tsx +397 -0
- package/components/detail-page/bubble-tail-overlay.tsx +209 -0
- package/components/detail-page/canvas-context-menu.tsx +234 -0
- package/components/detail-page/canvas-observer.tsx +68 -0
- package/components/detail-page/canvas-overlay-host.tsx +44 -0
- package/components/detail-page/canvas-store-facade.ts +51 -0
- package/components/detail-page/chart-inspector.tsx +531 -0
- package/components/detail-page/design-reference-picker.tsx +383 -0
- package/components/detail-page/detail-page-basic-shapes.tsx +180 -0
- package/components/detail-page/detail-page-brand-gifs-panel.tsx +261 -0
- package/components/detail-page/detail-page-brand-kit-panel.tsx +77 -0
- package/components/detail-page/detail-page-brand-panel-header.tsx +44 -0
- package/components/detail-page/detail-page-charts-panel.tsx +104 -0
- package/components/detail-page/detail-page-decorations-panel.tsx +125 -0
- package/components/detail-page/detail-page-download-dialog.tsx +524 -0
- package/components/detail-page/detail-page-editor.tsx +974 -0
- package/components/detail-page/detail-page-elements-panel.tsx +117 -0
- package/components/detail-page/detail-page-font-picker.tsx +231 -0
- package/components/detail-page/detail-page-history-buttons.tsx +87 -0
- package/components/detail-page/detail-page-host-context.tsx +465 -0
- package/components/detail-page/detail-page-icons-panel.tsx +251 -0
- package/components/detail-page/detail-page-konva-json-preview.tsx +474 -0
- package/components/detail-page/detail-page-layers-panel.tsx +618 -0
- package/components/detail-page/detail-page-my-images-panel.tsx +179 -0
- package/components/detail-page/detail-page-my-shapes-panel.tsx +174 -0
- package/components/detail-page/detail-page-page-toolbar.tsx +171 -0
- package/components/detail-page/detail-page-pages-panel.tsx +299 -0
- package/components/detail-page/detail-page-pages-timeline.tsx +79 -0
- package/components/detail-page/detail-page-photos-panel.tsx +257 -0
- package/components/detail-page/detail-page-properties-panel.tsx +2680 -0
- package/components/detail-page/detail-page-qr-panel.tsx +137 -0
- package/components/detail-page/detail-page-references-panel.tsx +166 -0
- package/components/detail-page/detail-page-selection.ts +44 -0
- package/components/detail-page/detail-page-shapes-panel.tsx +16 -0
- package/components/detail-page/detail-page-sidebar-sections.tsx +324 -0
- package/components/detail-page/detail-page-tables-panel.tsx +106 -0
- package/components/detail-page/detail-page-text-panel.tsx +179 -0
- package/components/detail-page/detail-page-thumbnail-bus.ts +42 -0
- package/components/detail-page/edit-quota-ui.tsx +150 -0
- package/components/detail-page/editor-history.ts +56 -0
- package/components/detail-page/editor-hotkeys.tsx +165 -0
- package/components/detail-page/element-recents-strip.tsx +105 -0
- package/components/detail-page/element-rects.ts +82 -0
- package/components/detail-page/fill-control.tsx +261 -0
- package/components/detail-page/find-replace-panel.tsx +252 -0
- package/components/detail-page/generation-progress-fill.tsx +57 -0
- package/components/detail-page/gif-animator.tsx +184 -0
- package/components/detail-page/gif-effect-picker.tsx +136 -0
- package/components/detail-page/group-drill-in.tsx +219 -0
- package/components/detail-page/group-prompt-edit-panel.tsx +154 -0
- package/components/detail-page/hover-highlight-overlay.tsx +111 -0
- package/components/detail-page/hovered-layer.ts +34 -0
- package/components/detail-page/inspector-controls.tsx +175 -0
- package/components/detail-page/leviosa-canvas-workspace.tsx +313 -0
- package/components/detail-page/nested-selection-overlay.tsx +364 -0
- package/components/detail-page/panel-search-input.tsx +49 -0
- package/components/detail-page/prompt-edit-panel.tsx +146 -0
- package/components/detail-page/section-height-handle.tsx +276 -0
- package/components/detail-page/section-reauthor-controller.tsx +210 -0
- package/components/detail-page/spec-prompt-edit-panel.tsx +178 -0
- package/components/detail-page/spec-resize-absorber.tsx +149 -0
- package/components/detail-page/svg-prompt-edit-panel.tsx +139 -0
- package/components/detail-page/table-canvas-overlay.tsx +707 -0
- package/components/detail-page/table-inspector.tsx +586 -0
- package/components/ui/button.tsx +64 -0
- package/components/ui/command.tsx +175 -0
- package/components/ui/dialog.tsx +167 -0
- package/components/ui/label.tsx +24 -0
- package/components/ui/select.tsx +190 -0
- package/components/ui/slider.tsx +63 -0
- package/components/ui/switch.tsx +35 -0
- package/components/ui/tooltip.tsx +57 -0
- package/config/detail-page-bundle-font-tags.json +39 -0
- package/config/detail-page-fonts.json +373 -0
- package/index.ts +24 -0
- package/lib/cardnews/font-loader.ts +306 -0
- package/lib/detail-page/animation-sniff.ts +101 -0
- package/lib/detail-page/asset-bytes-url.ts +70 -0
- package/lib/detail-page/basic-shapes.ts +603 -0
- package/lib/detail-page/canvas-menu.ts +182 -0
- package/lib/detail-page/chart/defaults.ts +283 -0
- package/lib/detail-page/chart/format.ts +66 -0
- package/lib/detail-page/chart/normalize.ts +149 -0
- package/lib/detail-page/chart/palette.ts +85 -0
- package/lib/detail-page/chart/paste.ts +82 -0
- package/lib/detail-page/chart/preview.ts +78 -0
- package/lib/detail-page/chart/render.ts +188 -0
- package/lib/detail-page/chart/renderers/bar-h.ts +103 -0
- package/lib/detail-page/chart/renderers/bar-v.ts +213 -0
- package/lib/detail-page/chart/renderers/donut.ts +186 -0
- package/lib/detail-page/chart/renderers/gauge.ts +96 -0
- package/lib/detail-page/chart/renderers/line.ts +143 -0
- package/lib/detail-page/chart/renderers/shared.ts +263 -0
- package/lib/detail-page/chart/renderers/stack.ts +121 -0
- package/lib/detail-page/chart/sync.ts +92 -0
- package/lib/detail-page/chart/types.ts +145 -0
- package/lib/detail-page/css-color.ts +34 -0
- package/lib/detail-page/data-gif-payload.ts +167 -0
- package/lib/detail-page/design-reference.ts +244 -0
- package/lib/detail-page/distribute.ts +89 -0
- package/lib/detail-page/editor-routes.ts +10 -0
- package/lib/detail-page/element-recents.ts +167 -0
- package/lib/detail-page/find-replace.ts +120 -0
- package/lib/detail-page/format-painter.ts +159 -0
- package/lib/detail-page/gif-frames.ts +216 -0
- package/lib/detail-page/gif-timeline.ts +65 -0
- package/lib/detail-page/group-action.ts +62 -0
- package/lib/detail-page/hangul-roman.ts +58 -0
- package/lib/detail-page/icon-curated.ts +290 -0
- package/lib/detail-page/icon-fuzzy.ts +250 -0
- package/lib/detail-page/icon-keywords.generated.ts +3766 -0
- package/lib/detail-page/icon-keywords.ko.ts +524 -0
- package/lib/detail-page/icon-search.ts +257 -0
- package/lib/detail-page/icons.ts +67 -0
- package/lib/detail-page/image-credit.ts +121 -0
- package/lib/detail-page/image-data-uri.ts +29 -0
- package/lib/detail-page/insert-image.ts +75 -0
- package/lib/detail-page/insert-shape.ts +49 -0
- package/lib/detail-page/korean-dictionary.ts +187 -0
- package/lib/detail-page/layer-move.ts +257 -0
- package/lib/detail-page/new-product-draft-store.ts +105 -0
- package/lib/detail-page/new-product-draft.ts +283 -0
- package/lib/detail-page/personal-images-refresh.ts +30 -0
- package/lib/detail-page/product-source.ts +587 -0
- package/lib/detail-page/qr-code.ts +214 -0
- package/lib/detail-page/reference-image.ts +103 -0
- package/lib/detail-page/reference-upload.ts +181 -0
- package/lib/detail-page/replace-page.ts +35 -0
- package/lib/detail-page/replace-with-gif.ts +251 -0
- package/lib/detail-page/section-height.ts +131 -0
- package/lib/detail-page/section-reauthor-bus.ts +61 -0
- package/lib/detail-page/shape-to-image.ts +219 -0
- package/lib/detail-page/spec-group/clipboard.ts +35 -0
- package/lib/detail-page/spec-group/sync.ts +377 -0
- package/lib/detail-page/spec-group/text-metrics.ts +48 -0
- package/lib/detail-page/stock-photos.ts +88 -0
- package/lib/detail-page/svg-colors.ts +74 -0
- package/lib/detail-page/table/defaults.ts +344 -0
- package/lib/detail-page/table/edit.ts +312 -0
- package/lib/detail-page/table/harvest.ts +103 -0
- package/lib/detail-page/table/normalize.ts +125 -0
- package/lib/detail-page/table/paste.ts +49 -0
- package/lib/detail-page/table/preview.ts +66 -0
- package/lib/detail-page/table/render.ts +388 -0
- package/lib/detail-page/table/sync.ts +107 -0
- package/lib/detail-page/table/types.ts +102 -0
- package/lib/detail-page/text-gif-layout.ts +245 -0
- package/lib/detail-page/text-gif-payload.ts +67 -0
- package/lib/detail-page/text-presets.ts +230 -0
- package/lib/detail-page/use-fake-progress.ts +67 -0
- package/lib/detail-page/z-order.ts +82 -0
- package/lib/detail-page-canvas/bubble-path.ts +190 -0
- package/lib/detail-page-canvas/canvas-key.ts +22 -0
- package/lib/detail-page-canvas/clip-rect.ts +65 -0
- package/lib/detail-page-canvas/custom-props-adapter.ts +219 -0
- package/lib/detail-page-canvas/editor-fonts.ts +161 -0
- package/lib/detail-page-canvas/export/ai.ts +413 -0
- package/lib/detail-page-canvas/export/color.ts +35 -0
- package/lib/detail-page-canvas/export/document-model.ts +78 -0
- package/lib/detail-page-canvas/export/export-files.ts +290 -0
- package/lib/detail-page-canvas/export/font-subset.ts +264 -0
- package/lib/detail-page-canvas/export/gif-export.ts +310 -0
- package/lib/detail-page-canvas/export/gif-plan.ts +95 -0
- package/lib/detail-page-canvas/export/mp4-encode.ts +158 -0
- package/lib/detail-page-canvas/export/mp4-support.ts +22 -0
- package/lib/detail-page-canvas/export/pdf/geometry.ts +309 -0
- package/lib/detail-page-canvas/export/pdf/inline-svg.ts +399 -0
- package/lib/detail-page-canvas/export/pdf/resources.ts +443 -0
- package/lib/detail-page-canvas/export/pdf/text-ops.ts +81 -0
- package/lib/detail-page-canvas/export/pdf/writer.ts +109 -0
- package/lib/detail-page-canvas/export/psd.ts +354 -0
- package/lib/detail-page-canvas/export/raster.ts +255 -0
- package/lib/detail-page-canvas/export/svg.ts +479 -0
- package/lib/detail-page-canvas/export/text-layout.ts +142 -0
- package/lib/detail-page-canvas/font-catalog.ts +177 -0
- package/lib/detail-page-canvas/font-tags.ts +47 -0
- package/lib/detail-page-canvas/gif-web-fonts.ts +90 -0
- package/lib/detail-page-canvas/konva-fallback.ts +477 -0
- package/lib/detail-page-canvas/text-background-plan.ts +124 -0
- package/lib/detail-page-canvas/text-highlight-bands.ts +127 -0
- package/lib/utils.ts +10 -0
- package/package.json +68 -0
- package/types/commerce.ts +171 -0
- package/types/detail-page-api.ts +200 -0
- package/types/detail-page-canvas.ts +20 -0
- package/types/fontkit.d.ts +42 -0
- package/types/gifenc.d.ts +51 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 아이콘 검색용 한국어 → 영어 키워드 사전.
|
|
3
|
+
*
|
|
4
|
+
* 아이콘 제공처(Iconify)는 **아이콘 이름과 별칭이 전부 영어**다. 스톡 사진은 `locale=ko-KR`을
|
|
5
|
+
* 넘길 데라도 있었지만(`src/app/api/stock-photos/route.ts`) 여기엔 그런 것이 없다. 그래서
|
|
6
|
+
* "배송"을 그대로 넘기면 0건이다 — 이 사전이 없으면 기능 자체가 안 쓰인다.
|
|
7
|
+
*
|
|
8
|
+
* 값은 **순서 있는 배열**이다. 앞이 1순위고, 결과가 모자랄 때만 뒤를 덧댄다(프록시가
|
|
9
|
+
* 그렇게 쓴다). 그래서 "가장 그럴듯한 하나"를 맨 앞에 둔다.
|
|
10
|
+
*
|
|
11
|
+
* 수록 기준은 **상세페이지에서 실제로 찍히는 말**이다. 일반 한국어 사전이 아니다.
|
|
12
|
+
* 여기 없는 말은 자동 생성분(`icon-keywords.generated.ts`)이 받고, 그것도 없으면
|
|
13
|
+
* 국립국어원에 한 번 물어본다(`korean-dictionary.ts`).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { ICON_KEYWORDS_GENERATED } from "./icon-keywords.generated";
|
|
17
|
+
|
|
18
|
+
export const ICON_KEYWORDS_KO: Readonly<Record<string, readonly string[]>> = {
|
|
19
|
+
// ── 배송·물류 ───────────────────────────────────────────────────────────────
|
|
20
|
+
배송: ["truck", "package", "delivery"],
|
|
21
|
+
무료배송: ["truck", "gift", "package"],
|
|
22
|
+
당일발송: ["truck-fast", "clock", "package"],
|
|
23
|
+
익일배송: ["truck-fast", "calendar", "package"],
|
|
24
|
+
로켓배송: ["rocket", "truck-fast"],
|
|
25
|
+
택배: ["package", "truck", "box"],
|
|
26
|
+
발송: ["send", "package", "truck"],
|
|
27
|
+
출고: ["package-export", "truck", "box"],
|
|
28
|
+
입고: ["package-import", "box", "warehouse"],
|
|
29
|
+
포장: ["package", "box", "gift"],
|
|
30
|
+
박스: ["box", "package"],
|
|
31
|
+
운송장: ["receipt", "barcode", "package"],
|
|
32
|
+
물류: ["warehouse", "truck", "forklift"],
|
|
33
|
+
창고: ["warehouse", "building-warehouse", "box"],
|
|
34
|
+
해외배송: ["world", "plane", "truck"],
|
|
35
|
+
항공: ["plane", "airplane"],
|
|
36
|
+
선박: ["ship", "boat"],
|
|
37
|
+
추적: ["map-pin", "route", "search"],
|
|
38
|
+
도착: ["map-pin", "flag", "check"],
|
|
39
|
+
|
|
40
|
+
// ── 주문·결제 ───────────────────────────────────────────────────────────────
|
|
41
|
+
주문: ["shopping-cart", "clipboard-list", "receipt"],
|
|
42
|
+
장바구니: ["shopping-cart", "shopping-bag"],
|
|
43
|
+
구매: ["shopping-bag", "credit-card", "shopping-cart"],
|
|
44
|
+
결제: ["credit-card", "wallet", "cash"],
|
|
45
|
+
카드: ["credit-card", "wallet"],
|
|
46
|
+
현금: ["cash", "coins", "banknote"],
|
|
47
|
+
계좌이체: ["building-bank", "arrows-exchange", "cash"],
|
|
48
|
+
간편결제: ["device-mobile", "credit-card", "wallet"],
|
|
49
|
+
영수증: ["receipt", "file-invoice"],
|
|
50
|
+
세금계산서: ["file-invoice", "receipt-tax"],
|
|
51
|
+
가격: ["tag", "currency-won", "price-tag"],
|
|
52
|
+
할인: ["discount", "tag", "percentage"],
|
|
53
|
+
세일: ["discount", "tag", "flame"],
|
|
54
|
+
특가: ["flame", "discount", "tag"],
|
|
55
|
+
쿠폰: ["ticket", "coupon", "tag"],
|
|
56
|
+
적립: ["coin", "gift", "star"],
|
|
57
|
+
포인트: ["coin", "star", "diamond"],
|
|
58
|
+
마일리지: ["coin", "award", "star"],
|
|
59
|
+
무이자: ["percentage", "credit-card", "calendar"],
|
|
60
|
+
할부: ["calendar", "credit-card", "divide"],
|
|
61
|
+
환불: ["arrow-back-up", "receipt-refund", "cash"],
|
|
62
|
+
반품: ["arrow-back-up", "package", "truck-return"],
|
|
63
|
+
교환: ["arrows-exchange", "refresh", "repeat"],
|
|
64
|
+
취소: ["x", "circle-x", "ban"],
|
|
65
|
+
|
|
66
|
+
// ── 신뢰·인증 ───────────────────────────────────────────────────────────────
|
|
67
|
+
정품: ["certificate", "rosette-discount-check", "shield-check"],
|
|
68
|
+
인증: ["certificate", "badge-check", "shield-check"],
|
|
69
|
+
검증: ["shield-check", "check", "search"],
|
|
70
|
+
보증: ["shield", "certificate", "umbrella"],
|
|
71
|
+
품질보증: ["shield-check", "award", "certificate"],
|
|
72
|
+
특허: ["certificate", "award", "bulb"],
|
|
73
|
+
상표: ["trademark", "copyright", "certificate"],
|
|
74
|
+
공식: ["badge-check", "certificate", "building"],
|
|
75
|
+
검사: ["microscope", "clipboard-check", "search"],
|
|
76
|
+
시험성적서: ["file-certificate", "clipboard-check", "flask"],
|
|
77
|
+
안전: ["shield-check", "helmet", "lock"],
|
|
78
|
+
안심: ["shield-check", "heart-handshake", "lock"],
|
|
79
|
+
신뢰: ["heart-handshake", "shield-check", "thumb-up"],
|
|
80
|
+
수상: ["award", "trophy", "medal"],
|
|
81
|
+
"1위": ["trophy", "medal", "crown"],
|
|
82
|
+
베스트: ["trophy", "star", "flame"],
|
|
83
|
+
추천: ["thumb-up", "star", "heart"],
|
|
84
|
+
인기: ["flame", "trending-up", "heart"],
|
|
85
|
+
신상품: ["sparkles", "star", "tag"],
|
|
86
|
+
한정: ["clock", "flame", "lock"],
|
|
87
|
+
품절: ["package-off", "x", "alert-circle"],
|
|
88
|
+
재입고: ["refresh", "package", "bell"],
|
|
89
|
+
|
|
90
|
+
// ── 제품 속성 ───────────────────────────────────────────────────────────────
|
|
91
|
+
방수: ["droplet-off", "umbrella", "shield"],
|
|
92
|
+
생활방수: ["droplet", "shield", "umbrella"],
|
|
93
|
+
방진: ["wind", "shield", "filter"],
|
|
94
|
+
방염: ["flame-off", "shield", "fire-extinguisher"],
|
|
95
|
+
내구성: ["shield", "hammer", "armchair"],
|
|
96
|
+
경량: ["feather", "wind", "scale"],
|
|
97
|
+
초경량: ["feather", "wind"],
|
|
98
|
+
가벼움: ["feather", "wind", "scale"],
|
|
99
|
+
튼튼: ["shield", "hammer", "muscle"],
|
|
100
|
+
통기성: ["wind", "air-conditioning", "grid-dots"],
|
|
101
|
+
흡수: ["droplet", "sponge", "arrow-down"],
|
|
102
|
+
건조: ["sun", "wind", "wash-dry"],
|
|
103
|
+
세탁: ["wash-machine", "bubble", "shirt"],
|
|
104
|
+
손세탁: ["hand-stop", "bubble", "wash"],
|
|
105
|
+
드라이클리닝: ["wash-dry-clean", "shirt", "hanger"],
|
|
106
|
+
다림질: ["ironing", "shirt"],
|
|
107
|
+
소재: ["texture", "layers", "shirt"],
|
|
108
|
+
원단: ["texture", "shirt", "layers"],
|
|
109
|
+
면: ["plant", "shirt", "texture"],
|
|
110
|
+
가죽: ["shirt", "texture", "bag"],
|
|
111
|
+
스테인리스: ["tools-kitchen", "shine", "shield"],
|
|
112
|
+
실리콘: ["droplet", "texture", "shield"],
|
|
113
|
+
친환경: ["leaf", "recycle", "plant"],
|
|
114
|
+
재활용: ["recycle", "refresh", "leaf"],
|
|
115
|
+
무독성: ["leaf", "shield-check", "flask-off"],
|
|
116
|
+
무향: ["wind", "flask-off"],
|
|
117
|
+
저자극: ["feather", "heart", "shield"],
|
|
118
|
+
국내생산: ["flag", "building-factory", "map-pin"],
|
|
119
|
+
수입: ["world", "plane", "package-import"],
|
|
120
|
+
원산지: ["map-pin", "world", "flag"],
|
|
121
|
+
제조: ["building-factory", "tools", "settings"],
|
|
122
|
+
성분: ["flask", "list-details", "leaf"],
|
|
123
|
+
함량: ["chart-pie", "flask", "percentage"],
|
|
124
|
+
용량: ["bottle", "ruler", "database"],
|
|
125
|
+
중량: ["scale", "weight"],
|
|
126
|
+
사이즈: ["ruler", "resize", "arrows-maximize"],
|
|
127
|
+
치수: ["ruler", "dimensions", "resize"],
|
|
128
|
+
규격: ["ruler", "dimensions", "clipboard-list"],
|
|
129
|
+
색상: ["palette", "color-swatch", "droplet"],
|
|
130
|
+
옵션: ["adjustments", "list", "settings"],
|
|
131
|
+
구성품: ["box", "list", "package"],
|
|
132
|
+
세트: ["boxes", "package", "layers"],
|
|
133
|
+
유통기한: ["calendar-time", "clock", "hourglass"],
|
|
134
|
+
제조일자: ["calendar", "building-factory"],
|
|
135
|
+
보관: ["fridge", "box", "temperature"],
|
|
136
|
+
냉장: ["fridge", "snowflake", "temperature"],
|
|
137
|
+
냉동: ["snowflake", "fridge"],
|
|
138
|
+
실온: ["temperature", "home", "sun"],
|
|
139
|
+
|
|
140
|
+
// ── 사용·기능 ───────────────────────────────────────────────────────────────
|
|
141
|
+
사용법: ["book", "list-numbers", "help"],
|
|
142
|
+
설명서: ["book", "file-text", "help"],
|
|
143
|
+
주의사항: ["alert-triangle", "info-circle", "exclamation-mark"],
|
|
144
|
+
경고: ["alert-triangle", "alert-circle"],
|
|
145
|
+
금지: ["ban", "circle-x", "hand-stop"],
|
|
146
|
+
필수: ["asterisk", "alert-circle", "star"],
|
|
147
|
+
간편: ["click", "wand", "bolt"],
|
|
148
|
+
원터치: ["click", "hand-finger", "bolt"],
|
|
149
|
+
자동: ["settings-automation", "robot", "bolt"],
|
|
150
|
+
수동: ["hand-finger", "adjustments", "tool"],
|
|
151
|
+
조절: ["adjustments", "settings", "sliders"],
|
|
152
|
+
분리형: ["separator", "unlink", "layers-difference"],
|
|
153
|
+
접이식: ["fold", "arrows-minimize", "layers"],
|
|
154
|
+
휴대: ["briefcase", "backpack", "device-mobile"],
|
|
155
|
+
거치: ["device-desktop", "stand", "anchor"],
|
|
156
|
+
충전: ["battery-charging", "plug", "bolt"],
|
|
157
|
+
배터리: ["battery", "battery-charging"],
|
|
158
|
+
무선: ["wifi", "bluetooth", "antenna"],
|
|
159
|
+
블루투스: ["bluetooth", "device-mobile"],
|
|
160
|
+
방수등급: ["droplet-off", "shield", "certificate"],
|
|
161
|
+
소음: ["volume", "wave-square", "ear"],
|
|
162
|
+
저소음: ["volume-off", "moon", "ear-off"],
|
|
163
|
+
절전: ["bolt-off", "leaf", "plug-off"],
|
|
164
|
+
전력: ["bolt", "plug", "battery"],
|
|
165
|
+
온도: ["temperature", "thermometer", "sun"],
|
|
166
|
+
타이머: ["clock", "hourglass", "alarm"],
|
|
167
|
+
방향: ["arrows-move", "compass", "navigation"],
|
|
168
|
+
|
|
169
|
+
// ── 고객·응대 ───────────────────────────────────────────────────────────────
|
|
170
|
+
고객센터: ["headset", "phone", "message-circle"],
|
|
171
|
+
상담: ["message-circle", "headset", "user-question"],
|
|
172
|
+
문의: ["message-question", "help-circle", "mail"],
|
|
173
|
+
전화: ["phone", "phone-call"],
|
|
174
|
+
카톡: ["message-circle", "brand-kakao"],
|
|
175
|
+
카카오톡: ["message-circle", "brand-kakao"],
|
|
176
|
+
채팅: ["message-circle", "messages"],
|
|
177
|
+
이메일: ["mail", "at", "send"],
|
|
178
|
+
운영시간: ["clock", "calendar", "building-store"],
|
|
179
|
+
휴무: ["calendar-off", "moon", "door"],
|
|
180
|
+
공지: ["speakerphone", "bell", "info-circle"],
|
|
181
|
+
안내: ["info-circle", "help-circle", "book"],
|
|
182
|
+
후기: ["star", "message-circle", "thumb-up"],
|
|
183
|
+
리뷰: ["star", "message-circle", "pencil"],
|
|
184
|
+
별점: ["star", "stars", "star-half"],
|
|
185
|
+
평점: ["star", "chart-bar", "award"],
|
|
186
|
+
질문: ["help-circle", "message-question", "question-mark"],
|
|
187
|
+
답변: ["message-reply", "check", "message-circle"],
|
|
188
|
+
|
|
189
|
+
// ── 브랜드·마케팅 ───────────────────────────────────────────────────────────
|
|
190
|
+
브랜드: ["award", "diamond", "crown"],
|
|
191
|
+
로고: ["copyright", "diamond", "award"],
|
|
192
|
+
이벤트: ["confetti", "gift", "calendar-event"],
|
|
193
|
+
증정: ["gift", "present", "sparkles"],
|
|
194
|
+
선물: ["gift", "present", "heart"],
|
|
195
|
+
사은품: ["gift", "package", "sparkles"],
|
|
196
|
+
체험: ["hand-finger", "flask", "eye"],
|
|
197
|
+
구독: ["repeat", "calendar", "bell"],
|
|
198
|
+
회원: ["user", "id-badge", "users"],
|
|
199
|
+
등급: ["award", "crown", "stairs"],
|
|
200
|
+
신규: ["sparkles", "plus", "star"],
|
|
201
|
+
재구매: ["repeat", "shopping-cart", "refresh"],
|
|
202
|
+
공유: ["share", "send", "users"],
|
|
203
|
+
링크: ["link", "external-link"],
|
|
204
|
+
홈페이지: ["world", "home", "browser"],
|
|
205
|
+
쇼핑몰: ["building-store", "shopping-bag", "world"],
|
|
206
|
+
매장: ["building-store", "map-pin", "door"],
|
|
207
|
+
지도: ["map", "map-pin", "navigation"],
|
|
208
|
+
위치: ["map-pin", "navigation", "target"],
|
|
209
|
+
|
|
210
|
+
// ── 수치·비교 ───────────────────────────────────────────────────────────────
|
|
211
|
+
비교: ["arrows-left-right", "columns", "scale"],
|
|
212
|
+
차이: ["arrows-diff", "minus", "chart-bar"],
|
|
213
|
+
증가: ["trending-up", "arrow-up", "chart-line"],
|
|
214
|
+
감소: ["trending-down", "arrow-down", "chart-line"],
|
|
215
|
+
성장: ["trending-up", "plant", "chart-line"],
|
|
216
|
+
통계: ["chart-bar", "chart-pie", "report-analytics"],
|
|
217
|
+
그래프: ["chart-line", "chart-bar", "chart-area"],
|
|
218
|
+
퍼센트: ["percentage", "chart-pie"],
|
|
219
|
+
순위: ["trophy", "list-numbers", "medal"],
|
|
220
|
+
누적: ["stack", "layers", "chart-bar"],
|
|
221
|
+
판매량: ["chart-bar", "shopping-cart", "trending-up"],
|
|
222
|
+
재고: ["package", "boxes", "database"],
|
|
223
|
+
|
|
224
|
+
// ── 시간·일정 ───────────────────────────────────────────────────────────────
|
|
225
|
+
시간: ["clock", "hourglass"],
|
|
226
|
+
날짜: ["calendar", "calendar-event"],
|
|
227
|
+
기간: ["calendar", "hourglass", "clock"],
|
|
228
|
+
마감: ["clock", "hourglass-off", "flag"],
|
|
229
|
+
즉시: ["bolt", "flash", "clock"],
|
|
230
|
+
빠름: ["bolt", "rocket", "truck-fast"],
|
|
231
|
+
"1년": ["calendar", "clock", "shield"],
|
|
232
|
+
"1개월": ["calendar-month", "clock"],
|
|
233
|
+
"24시간": ["clock-24", "clock", "moon"],
|
|
234
|
+
연중무휴: ["calendar", "infinity", "clock"],
|
|
235
|
+
|
|
236
|
+
// ── 사람·신체 ───────────────────────────────────────────────────────────────
|
|
237
|
+
사람: ["user", "users", "mood-smile"],
|
|
238
|
+
아기: ["baby-carriage", "mood-kid", "heart"],
|
|
239
|
+
어린이: ["mood-kid", "school", "baby-carriage"],
|
|
240
|
+
여성: ["gender-female", "user", "woman"],
|
|
241
|
+
남성: ["gender-male", "user", "man"],
|
|
242
|
+
가족: ["users", "home", "heart"],
|
|
243
|
+
반려동물: ["dog", "cat", "paw"],
|
|
244
|
+
강아지: ["dog", "paw"],
|
|
245
|
+
고양이: ["cat", "paw"],
|
|
246
|
+
피부: ["hand", "sparkles", "droplet"],
|
|
247
|
+
머리카락: ["scissors", "user", "wind"],
|
|
248
|
+
건강: ["heart", "heartbeat", "activity"],
|
|
249
|
+
운동: ["barbell", "run", "activity"],
|
|
250
|
+
수면: ["moon", "bed", "zzz"],
|
|
251
|
+
다이어트: ["scale", "run", "salad"],
|
|
252
|
+
|
|
253
|
+
// ── 생활·카테고리 ───────────────────────────────────────────────────────────
|
|
254
|
+
주방: ["tools-kitchen", "chef-hat", "cooker"],
|
|
255
|
+
요리: ["chef-hat", "cooker", "tools-kitchen"],
|
|
256
|
+
음식: ["bowl", "meat", "salad"],
|
|
257
|
+
음료: ["cup", "bottle", "glass"],
|
|
258
|
+
커피: ["coffee", "cup"],
|
|
259
|
+
침실: ["bed", "moon", "lamp"],
|
|
260
|
+
욕실: ["bath", "shower", "droplet"],
|
|
261
|
+
청소: ["spray", "brush", "trash"],
|
|
262
|
+
수납: ["box", "archive", "layout-grid"],
|
|
263
|
+
가구: ["armchair", "sofa", "table"],
|
|
264
|
+
조명: ["bulb", "lamp", "sun"],
|
|
265
|
+
전자제품: ["device-laptop", "plug", "cpu"],
|
|
266
|
+
의류: ["shirt", "hanger", "jacket"],
|
|
267
|
+
신발: ["shoe", "footprint"],
|
|
268
|
+
가방: ["backpack", "briefcase", "shopping-bag"],
|
|
269
|
+
화장품: ["perfume", "droplet", "sparkles"],
|
|
270
|
+
문구: ["pencil", "notebook", "paperclip"],
|
|
271
|
+
자동차: ["car", "steering-wheel"],
|
|
272
|
+
캠핑: ["tent", "campfire", "mountain"],
|
|
273
|
+
여행: ["plane", "luggage", "map"],
|
|
274
|
+
사무실: ["building", "device-desktop", "briefcase"],
|
|
275
|
+
|
|
276
|
+
// ── 식품·식자재 ─────────────────────────────────────────────────────────────
|
|
277
|
+
// 상세페이지의 절반이 먹는 것이다. 여기가 비어 있어서 "사과"가 0건이었다 —
|
|
278
|
+
// 영어로 `apple`을 치면 나오는데 한글로 치면 안 나오는 것은 그냥 고장이다.
|
|
279
|
+
사과: ["apple"],
|
|
280
|
+
바나나: ["banana"],
|
|
281
|
+
딸기: ["strawberry", "cherry"],
|
|
282
|
+
포도: ["grapes", "grape"],
|
|
283
|
+
수박: ["watermelon", "melon"],
|
|
284
|
+
오렌지: ["orange"],
|
|
285
|
+
레몬: ["lemon"],
|
|
286
|
+
복숭아: ["peach"],
|
|
287
|
+
체리: ["cherry"],
|
|
288
|
+
블루베리: ["blueberry", "cherry"],
|
|
289
|
+
아보카도: ["avocado"],
|
|
290
|
+
과일: ["apple", "cherry", "orange"],
|
|
291
|
+
채소: ["broccoli", "carrot", "plant"],
|
|
292
|
+
당근: ["carrot"],
|
|
293
|
+
토마토: ["tomato"],
|
|
294
|
+
감자: ["potato"],
|
|
295
|
+
고구마: ["potato", "plant"],
|
|
296
|
+
양파: ["onion"],
|
|
297
|
+
마늘: ["garlic"],
|
|
298
|
+
브로콜리: ["broccoli"],
|
|
299
|
+
옥수수: ["corn"],
|
|
300
|
+
고추: ["pepper", "chili"],
|
|
301
|
+
버섯: ["mushroom"],
|
|
302
|
+
콩: ["bean", "grain"],
|
|
303
|
+
견과: ["nut", "peanut"],
|
|
304
|
+
쌀: ["grain", "rice", "bowl"],
|
|
305
|
+
곡물: ["grain", "wheat"],
|
|
306
|
+
계란: ["egg"],
|
|
307
|
+
빵: ["bread", "baguette"],
|
|
308
|
+
치즈: ["cheese"],
|
|
309
|
+
버터: ["butter"],
|
|
310
|
+
고기: ["meat", "beef"],
|
|
311
|
+
삼겹살: ["meat", "bacon"],
|
|
312
|
+
닭고기: ["meat", "egg-fried"],
|
|
313
|
+
생선: ["fish"],
|
|
314
|
+
새우: ["shrimp", "fish"],
|
|
315
|
+
해산물: ["fish", "shrimp"],
|
|
316
|
+
우유: ["milk"],
|
|
317
|
+
요거트: ["yogurt", "milk"],
|
|
318
|
+
꿀: ["honey", "beehive"],
|
|
319
|
+
국수: ["noodles", "bowl"],
|
|
320
|
+
라면: ["noodles", "bowl"],
|
|
321
|
+
피자: ["pizza"],
|
|
322
|
+
햄버거: ["burger", "hamburger"],
|
|
323
|
+
샐러드: ["salad", "bowl"],
|
|
324
|
+
케이크: ["cake"],
|
|
325
|
+
아이스크림: ["ice-cream"],
|
|
326
|
+
쿠키: ["cookie"],
|
|
327
|
+
사탕: ["candy"],
|
|
328
|
+
초콜릿: ["chocolate", "candy"],
|
|
329
|
+
와인: ["wine"],
|
|
330
|
+
맥주: ["beer"],
|
|
331
|
+
소주: ["bottle", "glass"],
|
|
332
|
+
주스: ["juice", "cup"],
|
|
333
|
+
물: ["droplet", "glass-water"],
|
|
334
|
+
소금: ["salt", "shaker"],
|
|
335
|
+
설탕: ["sugar", "candy"],
|
|
336
|
+
기름: ["bottle", "droplet"],
|
|
337
|
+
간식: ["cookie", "candy"],
|
|
338
|
+
도시락: ["lunchbox", "bowl"],
|
|
339
|
+
반려간식: ["bone", "cookie"],
|
|
340
|
+
|
|
341
|
+
// ── 가전·가구(외래어가 많은 자리) ───────────────────────────────────────────
|
|
342
|
+
냉장고: ["fridge", "refrigerator"],
|
|
343
|
+
세탁기: ["wash-machine", "washing-machine"],
|
|
344
|
+
건조기: ["wash-dry", "wind"],
|
|
345
|
+
전자레인지: ["microwave"],
|
|
346
|
+
에어컨: ["air-conditioning", "snowflake"],
|
|
347
|
+
선풍기: ["fan", "propeller"],
|
|
348
|
+
공기청정기: ["air-conditioning", "wind"],
|
|
349
|
+
청소기: ["vacuum-cleaner"],
|
|
350
|
+
정수기: ["glass-water", "droplet"],
|
|
351
|
+
노트북: ["device-laptop", "laptop"],
|
|
352
|
+
스마트폰: ["device-mobile", "phone"],
|
|
353
|
+
태블릿: ["device-tablet", "tablet"],
|
|
354
|
+
모니터: ["device-desktop", "monitor"],
|
|
355
|
+
키보드: ["keyboard"],
|
|
356
|
+
마우스: ["mouse"],
|
|
357
|
+
이어폰: ["headphones", "earbuds"],
|
|
358
|
+
헤드폰: ["headphones"],
|
|
359
|
+
충전기: ["battery-charging", "plug"],
|
|
360
|
+
텔레비전: ["device-tv", "television"],
|
|
361
|
+
소파: ["sofa", "armchair"],
|
|
362
|
+
침대: ["bed"],
|
|
363
|
+
책상: ["desk", "table"],
|
|
364
|
+
의자: ["armchair", "chair"],
|
|
365
|
+
옷장: ["hanger", "door"],
|
|
366
|
+
선반: ["shelf", "archive"],
|
|
367
|
+
거울: ["mirror"],
|
|
368
|
+
카펫: ["rug", "carpet"],
|
|
369
|
+
커튼: ["curtains", "blinds"],
|
|
370
|
+
화분: ["potted-plant", "plant"],
|
|
371
|
+
|
|
372
|
+
// ── 범용 기호 ───────────────────────────────────────────────────────────────
|
|
373
|
+
체크: ["check", "circle-check", "square-check"],
|
|
374
|
+
확인: ["check", "circle-check", "eye"],
|
|
375
|
+
완료: ["circle-check", "check", "flag"],
|
|
376
|
+
별: ["star", "stars"],
|
|
377
|
+
하트: ["heart", "heart-filled"],
|
|
378
|
+
화살표: ["arrow-right", "arrow-narrow-right", "chevron-right"],
|
|
379
|
+
플러스: ["plus", "circle-plus"],
|
|
380
|
+
마이너스: ["minus", "circle-minus"],
|
|
381
|
+
느낌표: ["exclamation-mark", "alert-circle"],
|
|
382
|
+
물음표: ["question-mark", "help-circle"],
|
|
383
|
+
전구: ["bulb", "bulb-filled"],
|
|
384
|
+
자물쇠: ["lock", "lock-open"],
|
|
385
|
+
검색: ["search", "zoom"],
|
|
386
|
+
설정: ["settings", "adjustments"],
|
|
387
|
+
다운로드: ["download", "arrow-down-circle"],
|
|
388
|
+
업로드: ["upload", "arrow-up-circle"],
|
|
389
|
+
인쇄: ["printer", "file"],
|
|
390
|
+
카메라: ["camera", "photo"],
|
|
391
|
+
동영상: ["video", "player-play"],
|
|
392
|
+
음악: ["music", "headphones"],
|
|
393
|
+
알림: ["bell", "bell-ringing"],
|
|
394
|
+
달력: ["calendar", "calendar-event"],
|
|
395
|
+
폴더: ["folder", "folder-open"],
|
|
396
|
+
파일: ["file", "file-text"],
|
|
397
|
+
휴지통: ["trash", "trash-x"],
|
|
398
|
+
손: ["hand-finger", "hand-stop", "click"],
|
|
399
|
+
눈: ["eye", "eye-off"],
|
|
400
|
+
불꽃: ["flame", "fire"],
|
|
401
|
+
물방울: ["droplet", "droplets"],
|
|
402
|
+
나뭇잎: ["leaf", "plant"],
|
|
403
|
+
태양: ["sun", "sunrise"],
|
|
404
|
+
달: ["moon", "moon-stars"],
|
|
405
|
+
구름: ["cloud", "cloud-rain"],
|
|
406
|
+
눈송이: ["snowflake", "snowman"],
|
|
407
|
+
지구: ["world", "globe"],
|
|
408
|
+
왕관: ["crown", "trophy"],
|
|
409
|
+
다이아몬드: ["diamond", "gem"],
|
|
410
|
+
방패: ["shield", "shield-check"],
|
|
411
|
+
깃발: ["flag", "flag-filled"],
|
|
412
|
+
메달: ["medal", "award"],
|
|
413
|
+
트로피: ["trophy", "award"],
|
|
414
|
+
선물상자: ["gift", "package"],
|
|
415
|
+
전화기: ["phone", "device-mobile"],
|
|
416
|
+
컴퓨터: ["device-desktop", "device-laptop"],
|
|
417
|
+
휴대폰: ["device-mobile", "phone"],
|
|
418
|
+
프린터: ["printer"],
|
|
419
|
+
마이크: ["microphone", "headset"],
|
|
420
|
+
스피커: ["speakerphone", "volume"],
|
|
421
|
+
시계: ["clock", "alarm"],
|
|
422
|
+
열쇠: ["key", "lock"],
|
|
423
|
+
톱니바퀴: ["settings", "gear"],
|
|
424
|
+
망치: ["hammer", "tools"],
|
|
425
|
+
가위: ["scissors", "cut"],
|
|
426
|
+
자: ["ruler", "ruler-measure"],
|
|
427
|
+
연필: ["pencil", "edit"],
|
|
428
|
+
붓: ["brush", "palette"],
|
|
429
|
+
책: ["book", "notebook"],
|
|
430
|
+
지폐: ["banknote", "cash"],
|
|
431
|
+
동전: ["coin", "coins"],
|
|
432
|
+
저울: ["scale", "balance"],
|
|
433
|
+
온도계: ["thermometer", "temperature"],
|
|
434
|
+
플러그: ["plug", "bolt"],
|
|
435
|
+
로켓: ["rocket", "trending-up"],
|
|
436
|
+
로봇: ["robot", "cpu"],
|
|
437
|
+
자석: ["magnet"],
|
|
438
|
+
퍼즐: ["puzzle", "components"],
|
|
439
|
+
타겟: ["target", "crosshair"],
|
|
440
|
+
무한: ["infinity", "repeat"],
|
|
441
|
+
} as const;
|
|
442
|
+
|
|
443
|
+
/** 한글이 하나라도 있으면 사전을 태운다. */
|
|
444
|
+
const HANGUL = /[가-힣]/;
|
|
445
|
+
|
|
446
|
+
/** 조사·공백·기호를 털어 낸다. "배송은" "무료 배송!" 이 같은 자리로 가야 한다. */
|
|
447
|
+
const PARTICLES =
|
|
448
|
+
/(?:은|는|이|가|을|를|에|에서|으로|로|와|과|의|도|만|까지|부터)$/;
|
|
449
|
+
|
|
450
|
+
function strip(token: string): string {
|
|
451
|
+
return token.replace(/[^0-9A-Za-z가-힣]/g, "");
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* 표제어 하나를 찾는다. **손으로 쓴 것이 언제나 먼저다.**
|
|
456
|
+
*
|
|
457
|
+
* 자동 생성분은 아이콘 이름에 실제로 있는 낱말만 담고 있어 넓지만, 어느 것이 1순위인지는
|
|
458
|
+
* 모른다("배송"의 `truck`이 `delivery`보다 앞이라는 것은 사람만 안다). 그래서 사람이
|
|
459
|
+
* 정해 둔 자리를 자동 생성이 밀어내지 못하게 순서를 고정한다.
|
|
460
|
+
*/
|
|
461
|
+
function lookupKeyword(key: string): readonly string[] | undefined {
|
|
462
|
+
return ICON_KEYWORDS_KO[key] ?? ICON_KEYWORDS_GENERATED[key];
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/** 부분일치용 키 목록. 긴 것부터, 손으로 쓴 것부터. 한 번만 만든다. */
|
|
466
|
+
let partialKeys: string[] | null = null;
|
|
467
|
+
|
|
468
|
+
function keysForPartialMatch(): string[] {
|
|
469
|
+
if (partialKeys) return partialKeys;
|
|
470
|
+
const byLength = (a: string, b: string) => b.length - a.length;
|
|
471
|
+
// 한 글자 키는 뺀다 — "화면"이 "면"으로, "숫자"가 "자"로 걸린다.
|
|
472
|
+
const hand = Object.keys(ICON_KEYWORDS_KO).filter((key) => key.length > 1).sort(byLength);
|
|
473
|
+
const baked = Object.keys(ICON_KEYWORDS_GENERATED)
|
|
474
|
+
.filter((key) => key.length > 1 && !ICON_KEYWORDS_KO[key])
|
|
475
|
+
.sort(byLength);
|
|
476
|
+
partialKeys = [...hand, ...baked];
|
|
477
|
+
return partialKeys;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* 한국어 질의를 영어 키워드 배열로 편다. 앞이 1순위다.
|
|
482
|
+
*
|
|
483
|
+
* 세 겹으로 찾는다.
|
|
484
|
+
* 1. 질의 전체가 사전에 있으면 그것(가장 정확하다).
|
|
485
|
+
* 2. 없으면 어절 단위로 — 조사를 떼고 다시 본다.
|
|
486
|
+
* 3. 그래도 없으면 사전 키가 질의 안에 들어 있는지 본다("무료배송" → "배송").
|
|
487
|
+
* 긴 키부터 봐서 "무료배송"이 "배송"보다 먼저 걸리게 한다.
|
|
488
|
+
*
|
|
489
|
+
* 한글이 없으면 원문을 그대로 돌려준다 — 영어로 치는 사람을 막지 않는다.
|
|
490
|
+
*/
|
|
491
|
+
export function expandKoreanQuery(query: string): string[] {
|
|
492
|
+
const text = query.trim();
|
|
493
|
+
if (!text) return [];
|
|
494
|
+
if (!HANGUL.test(text)) return [text];
|
|
495
|
+
|
|
496
|
+
const out: string[] = [];
|
|
497
|
+
const push = (words: readonly string[]) => {
|
|
498
|
+
for (const word of words) if (!out.includes(word)) out.push(word);
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
const whole = strip(text);
|
|
502
|
+
const exact = lookupKeyword(whole);
|
|
503
|
+
if (exact) push(exact);
|
|
504
|
+
|
|
505
|
+
if (!out.length) {
|
|
506
|
+
for (const token of text.split(/\s+/)) {
|
|
507
|
+
const bare = strip(token);
|
|
508
|
+
const hit = lookupKeyword(bare) ?? lookupKeyword(bare.replace(PARTICLES, ""));
|
|
509
|
+
if (hit) push(hit);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (!out.length) {
|
|
514
|
+
for (const key of keysForPartialMatch()) {
|
|
515
|
+
if (whole.includes(key)) {
|
|
516
|
+
push(lookupKeyword(key) ?? []);
|
|
517
|
+
break;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// 하나도 못 찾으면 원문이라도 넘긴다. 제공처가 별칭으로 걸러 줄 수도 있다.
|
|
523
|
+
return out.length ? out : [text];
|
|
524
|
+
}
|