@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 +17 -4
- package/dist/index.d.ts +14 -1
- package/dist/index.js +30 -3
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
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}` :
|
|
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" :
|
|
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}` :
|
|
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
|
};
|