@madeinbruno/atelier 0.6.0 → 0.7.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/README.md CHANGED
@@ -43,10 +43,10 @@ export default function Footer() {
43
43
  | 기호 | 숨은 뜻 | 툴팁 |
44
44
  |---|---|---|
45
45
  | 물세탁 빨래통 | 온도 자리 = 나이 (올해 − 2005) | he is 21 |
46
- | 표백 금지 | `quit`: 끊고 있는 것. 시작한 날(`since`, YYYY-MM-DD 한국 날짜)부터 며칠째인지 숫자가 ✕ 자리에. 없으면 ✕ | he is on day 12 without ○○ |
47
- | 건조 네모 | `wet`: 마음. 기호는 늘 텀블 건조 그대로, 켜 두면 툴팁만 | still not dry (켰을 때만) |
46
+ | 표백 금지 | `quit`: 끊고 있는 것. 시작한 날(`since`, YYYY-MM-DD 한국 날짜)부터 며칠째인지 숫자가 ✕ 자리에. 없으면 ✕ | he is on day 12 without ○○ / 없으면 he isn't giving anything up |
47
+ | 건조 네모 | `wet`: 마음. 기호는 늘 텀블 건조 그대로, 켜 두면 툴팁만 | still not dry / 꺼 두면 all dry |
48
48
  | 다리미 | `heat` 1~3 점: 뜨거울수록 열심히 하는 중 | he is taking it easy / busy / on fire |
49
- | 드라이클리닝 | `interest`: 요즘 관심 있는 것. `since`부터 1주일 동안 동그라미 안에 `icon`(고른 아이콘), 지나거나 없으면 ✕ | he is into ○○ (1주일 동안만) |
49
+ | 드라이클리닝 | `interest`: 요즘 관심 있는 것. `since`부터 1주일 동안 동그라미 안에 `icon`(고른 아이콘), 지나거나 없으면 ✕ | he is into ○○ (1주일 동안) / 없으면 nothing new lately |
50
50
 
51
51
  ```tsx
52
52
  <Tag
@@ -59,7 +59,20 @@ export default function Footer() {
59
59
  />
60
60
  ```
61
61
 
62
- 설정 화면에서 미리 보기용으로 `CareLabel`만 따로 쓸 수도 있어요 (`.mib-tag__care` 스타일 포함). 관심사가 아직 보이는 중인지는 `activeInterest(interest)`, 끊은 지 며칠째인지는 `quitDay(quit)`로 알 수 있어요. 고를 수 있는 아이콘은 `CARE_ICONS`에 있어요 (음악, 영화, 책, 사진, 게임, 코드, 커피, 식물, 운동, 글, 마음).
62
+ **상태는 한 곳에서 바꿔요.** 택 상태는 `apps/atelier`(atelier.madeinbruno.com)에서 주인이 바꾸고, 모든 서비스는 `fetchCareState()`로 같은 상태를 받아 그려요.
63
+
64
+ ```tsx
65
+ import { Tag, fetchCareState } from '@madeinbruno/atelier';
66
+
67
+ export default async function Footer() {
68
+ const care = await fetchCareState(); // 서버에서. Next.js에서는 1분 캐시
69
+ return <Tag service="hangoutwithme" care={care} />;
70
+ }
71
+ ```
72
+
73
+ - 받아 오지 못하면(3초 안에 응답이 없거나 에러) 기본 상태로 그려서 페이지가 깨지지 않아요.
74
+ - 주소는 `CARE_STATE_URL`(기본 `https://atelier.madeinbruno.com/api/care`). 다른 곳에서 받으려면 `fetchCareState(url)`.
75
+ - 설정 화면에서 미리 보기용으로 `CareLabel`만 따로 쓸 수도 있어요 (`.mib-tag__care` 스타일 포함). 관심사가 아직 보이는 중인지는 `activeInterest(interest)`, 끊은 지 며칠째인지는 `quitDay(quit)`로 알 수 있어요. 고를 수 있는 아이콘은 `CARE_ICONS`에 있어요 (음악, 영화, 책, 사진, 게임, 코드, 커피, 식물, 운동, 글, 마음).
63
76
 
64
77
  `madeinbruno` 글씨는 [Banquise](https://gitlab.com/bonjour-monde/fonderie/banquise-typeface)(Bonjour Monde, SIL Open Font License 1.1)로 쓴 글자를 SVG 그림으로 옮긴 거예요. 이 한 단어에만 쓰는 폰트라 폰트 파일을 싣지 않아요 (15KB → 1KB 미만, 글씨가 늦게 바뀌는 깜빡임도 없음).
65
78
 
package/dist/index.d.ts CHANGED
@@ -122,4 +122,17 @@ type TagProps = {
122
122
  };
123
123
  declare function Tag({ service, email, href, since, eyebrow, message, background, stitch, care, className, }: TagProps): react.JSX.Element;
124
124
 
125
- export { CARE_ICONS, type CareIcon, CareLabel, type CareState, DEFAULT_CARE_STATE, INTEREST_DAYS, Tag, type TagProps, activeInterest, isCareIcon, quitDay, todayInKorea };
125
+ /** 택 상태를 바꾸는 곳(apps/atelier)의 공개 주소 */
126
+ declare const CARE_STATE_URL = "https://atelier.madeinbruno.com/api/care";
127
+ /** 받아 온 값에서 지금 쓰는 항목만, 모양이 맞는 것만 꺼낸다 */
128
+ declare function normalizeCareState(raw: unknown): Required<CareState>;
129
+ /**
130
+ * 택 세탁 표시의 지금 상태를 atelier에서 받아 온다. 서버(예: Next.js 서버 컴포넌트)에서 부른다.
131
+ * Next.js에서는 1분 동안 캐시한다. 못 받으면(3초 안에 응답이 없거나 에러) 기본 상태로 그려서 페이지가 깨지지 않는다.
132
+ *
133
+ * const care = await fetchCareState();
134
+ * <Tag service="..." care={care} />
135
+ */
136
+ declare function fetchCareState(url?: string): Promise<Required<CareState>>;
137
+
138
+ export { CARE_ICONS, CARE_STATE_URL, type CareIcon, CareLabel, type CareState, DEFAULT_CARE_STATE, INTEREST_DAYS, Tag, type TagProps, activeInterest, fetchCareState, isCareIcon, normalizeCareState, quitDay, todayInKorea };
package/dist/index.js CHANGED
@@ -132,11 +132,11 @@ function CareLabel({ state }) {
132
132
  /* @__PURE__ */ jsx2("path", { d: "M3.2 8.1 L5.4 19.5 H18.6 L20.8 8.1" }),
133
133
  /* @__PURE__ */ jsx2("text", { x: "12", y: "16.6", textAnchor: "middle", children: age })
134
134
  ] }),
135
- /* @__PURE__ */ jsxs2(Symbol, { tip: quit && s.quit ? `he is on day ${quit} without ${s.quit.text}` : void 0, children: [
135
+ /* @__PURE__ */ jsxs2(Symbol, { tip: quit && s.quit ? `he is on day ${quit} without ${s.quit.text}` : "he isn't giving anything up", children: [
136
136
  /* @__PURE__ */ jsx2("path", { d: "M12 3.5 L21 19.5 H3 Z" }),
137
137
  quit ? /* @__PURE__ */ jsx2("text", { x: "12", y: "17.6", textAnchor: "middle", className: "mib-tag__care-small", children: quit }) : /* @__PURE__ */ jsx2("path", { d: "M7 8.5 L17 19.5 M17 8.5 L7 19.5" })
138
138
  ] }),
139
- /* @__PURE__ */ jsxs2(Symbol, { tip: s.wet ? "still not dry" : void 0, children: [
139
+ /* @__PURE__ */ jsxs2(Symbol, { tip: s.wet ? "still not dry" : "all dry", children: [
140
140
  /* @__PURE__ */ jsx2("rect", { x: "3.5", y: "3.5", width: "17", height: "17" }),
141
141
  /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "6" }),
142
142
  /* @__PURE__ */ jsx2(Dot, { cx: 12, cy: 12 })
@@ -145,7 +145,7 @@ function CareLabel({ state }) {
145
145
  /* @__PURE__ */ jsx2("path", { d: "M3 18 H21 C21 12.5 18.5 9.5 13.5 9.5 H7.5 C5.2 9.5 3.6 12.8 3 18 Z" }),
146
146
  dots.map((x) => /* @__PURE__ */ jsx2(Dot, { cx: x, cy: 14.2 }, x))
147
147
  ] }),
148
- /* @__PURE__ */ jsxs2(Symbol, { tip: interest ? `he is into ${interest.text}` : void 0, children: [
148
+ /* @__PURE__ */ jsxs2(Symbol, { tip: interest ? `he is into ${interest.text}` : "nothing new lately", children: [
149
149
  /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "8" }),
150
150
  !interest && /* @__PURE__ */ jsx2("path", { d: "M5.5 5.5 L18.5 18.5 M18.5 5.5 L5.5 18.5" }),
151
151
  interest?.icon && /* @__PURE__ */ jsx2("g", { className: "mib-tag__care-icon", transform: "translate(12 12) scale(0.42) translate(-12 -12)", children: CARE_ICONS[interest.icon].path })
@@ -199,14 +199,41 @@ function Tag({
199
199
  ] }) }) })
200
200
  ] }) });
201
201
  }
202
+
203
+ // src/fetchCareState.ts
204
+ var CARE_STATE_URL = "https://atelier.madeinbruno.com/api/care";
205
+ function normalizeCareState(raw) {
206
+ const v = raw ?? {};
207
+ const i = v.interest;
208
+ const q = v.quit;
209
+ return {
210
+ heat: v.heat === 1 || v.heat === 3 ? v.heat : 2,
211
+ interest: i && typeof i.text === "string" && i.text && typeof i.since === "string" ? { text: i.text, since: i.since, icon: isCareIcon(i.icon) ? i.icon : null } : null,
212
+ quit: q && typeof q.text === "string" && q.text && typeof q.since === "string" ? { text: q.text, since: q.since } : null,
213
+ wet: v.wet === true
214
+ };
215
+ }
216
+ async function fetchCareState(url = CARE_STATE_URL) {
217
+ try {
218
+ const init = { next: { revalidate: 60 }, signal: AbortSignal.timeout(3e3) };
219
+ const res = await fetch(url, init);
220
+ if (!res.ok) return DEFAULT_CARE_STATE;
221
+ return normalizeCareState(await res.json());
222
+ } catch {
223
+ return DEFAULT_CARE_STATE;
224
+ }
225
+ }
202
226
  export {
203
227
  CARE_ICONS,
228
+ CARE_STATE_URL,
204
229
  CareLabel,
205
230
  DEFAULT_CARE_STATE,
206
231
  INTEREST_DAYS,
207
232
  Tag,
208
233
  activeInterest,
234
+ fetchCareState,
209
235
  isCareIcon,
236
+ normalizeCareState,
210
237
  quitDay,
211
238
  todayInKorea
212
239
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madeinbruno/atelier",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "madeinbruno.com 서비스들이 같이 쓰는 공용 컴포넌트 (옷 만드는 작업실 컨셉: 택, 라벨, 도장…)",
5
5
  "license": "MIT",
6
6
  "author": "codingbotPark <pbk575@gmail.com>",