@olundot/ui 0.20.0-next.1 → 0.20.0-next.3
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/CHANGELOG.md +26 -0
- package/dist/index.d.ts +12 -6
- package/dist/index.js +247 -93
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @olundot/ui
|
|
2
2
|
|
|
3
|
+
## 0.20.0-next.3
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- b7176ad: `OlunLogo`가 `@olundot/tokens/brand`의 정본 데이터만 그린다. 모양이 바뀐다.
|
|
8
|
+
|
|
9
|
+
- 워드마크: Pretendard 800 글자(`<span>`) 대신 Montserrat 700 윤곽 SVG(자간 +0.03em). 접근 가능한 이름은 `role="img"` + `aria-label`(`OLUN`, 워드마크만이면 `OLUN.`)이다.
|
|
10
|
+
- MASTER(기본형): SVG 하나로 그리고 `symbolSize` 하나로 통째로 확대·축소한다. 간격 12px(`--space-3`) 대신 대문자 높이 H 기준 고정 비율(링 바깥 지름 1.24H, 궤도 점 끝 → O 0.55H)을 쓴다. 높이는 잉크에 맞춰 예전 심볼 상자보다 낮다(기본 `symbolSize` 28에서 약 17px).
|
|
11
|
+
- `fontSize`: 워드마크만 쓸 때(`showSymbol={false}`)의 글자 크기로만 쓴다. MASTER에서는 무시한다.
|
|
12
|
+
- 워드마크만 쓸 때 마침표 색이 `--accent`에서 `--accent-pop`으로 바뀐다(궤도 점과 같은 색 표식 `olun-accent`).
|
|
13
|
+
- `OlunSymbol`: 모양과 크기는 그대로다.
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 15f638e: 겹친 오버레이를 한 동작으로 함께 닫아도 포커스가 `<body>`로 떨어지지 않고 바깥 오버레이를 연 요소로 돌아간다. 바깥 오버레이가 먼저 사라지는 동안 안쪽 오버레이가 닫히는 애니메이션 중이어도 해당한다. Trigger가 있는 경우와 닫히는 동안 포커스가 다른 요소로 옮겨 간 경우는 그대로다.
|
|
18
|
+
- Updated dependencies [b7176ad]
|
|
19
|
+
- @olundot/tokens@0.18.0-next.1
|
|
20
|
+
|
|
21
|
+
## 0.20.0-next.2
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- 48c5a4d: `Tabs` `line`의 선택 표시가 다른 탭을 고를 때 그 탭으로 미끄러진다(`--dur-base`, `--ease-standard`). 처음 그릴 때와 크기가 바뀔 때는 바로 놓이고, 동작 줄이기 설정에서는 움직이지 않는다. 가로와 세로 모두 해당하며 `contained`는 그대로다.
|
|
26
|
+
- 목록 안에 `data-slot="tabs-indicator"` 요소(`aria-hidden`) 하나가 생긴다. 하이드레이션 전에는 기존 `::after` 밑줄이 보이고, 강조선이 자리를 잡으면 숨는다.
|
|
27
|
+
- 선택된 탭 라벨이 굵어져도 탭 폭이 바뀌지 않는다. 라벨에 굵기별 숨은 사본을 두어 폭을 미리 잡는다. 탭을 바꿔도 다른 탭이 밀리지 않는다.
|
|
28
|
+
|
|
3
29
|
## 0.20.0-next.1
|
|
4
30
|
|
|
5
31
|
### Minor Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -2055,11 +2055,11 @@ declare function TreeView<T extends TreeNode>({ nodes, selectedId, selectionAria
|
|
|
2055
2055
|
/**
|
|
2056
2056
|
* OLUN 브랜드 로고.
|
|
2057
2057
|
*
|
|
2058
|
-
* - symbol: O
|
|
2059
|
-
* - wordmark:
|
|
2060
|
-
* -
|
|
2058
|
+
* - symbol: O 링 + 우하단 accent-pop 궤도 점 (32px 초과/이하 두 광학 비율)
|
|
2059
|
+
* - wordmark: Montserrat 700 윤곽 `OLUN` + 단독일 때 accent-pop 마침표
|
|
2060
|
+
* - MASTER: symbol과 함께 쓰면 wordmark의 "."를 뺀다. 궤도 점이 마침표를 맡는다(점 두 개 경쟁 방지).
|
|
2061
2061
|
*
|
|
2062
|
-
*
|
|
2062
|
+
* 기하는 `@olundot/tokens/brand`의 정본 데이터(scripts/brand/build-brand-svg.mjs가 생성)에서만 온다.
|
|
2063
2063
|
*/
|
|
2064
2064
|
interface OlunSymbolProps {
|
|
2065
2065
|
/** 심볼 크기 px (기본 28) */
|
|
@@ -2068,9 +2068,15 @@ interface OlunSymbolProps {
|
|
|
2068
2068
|
}
|
|
2069
2069
|
declare function OlunSymbol({ size, className }: OlunSymbolProps): react_jsx_runtime.JSX.Element;
|
|
2070
2070
|
interface OlunLogoProps {
|
|
2071
|
-
/**
|
|
2071
|
+
/**
|
|
2072
|
+
* MASTER 크기. 심볼 240 상자 기준 px (기본 28).
|
|
2073
|
+
* 워드마크와 간격은 고정 비율로 함께 커진다. 32px 이하는 아이콘 비율 심볼을 쓴다.
|
|
2074
|
+
*/
|
|
2072
2075
|
symbolSize?: number;
|
|
2073
|
-
/**
|
|
2076
|
+
/**
|
|
2077
|
+
* 워드마크만 쓸 때(`showSymbol={false}`) 글자 크기 px (기본 18).
|
|
2078
|
+
* MASTER에서는 쓰지 않는다. MASTER 크기는 `symbolSize` 하나로 정한다.
|
|
2079
|
+
*/
|
|
2074
2080
|
fontSize?: number;
|
|
2075
2081
|
/** 심볼 표시 여부 (기본 true) */
|
|
2076
2082
|
showSymbol?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -3020,12 +3020,12 @@ var tabsListVariants = cva8(
|
|
|
3020
3020
|
{
|
|
3021
3021
|
variant: "line",
|
|
3022
3022
|
orientation: "horizontal",
|
|
3023
|
-
className: "border-b border-[var(--border-subtle)] gap-[var(--space-6)] overflow-x-auto overflow-y-hidden"
|
|
3023
|
+
className: "group/tabs-list relative border-b border-[var(--border-subtle)] gap-[var(--space-6)] overflow-x-auto overflow-y-hidden"
|
|
3024
3024
|
},
|
|
3025
3025
|
{
|
|
3026
3026
|
variant: "line",
|
|
3027
3027
|
orientation: "vertical",
|
|
3028
|
-
className: "border-r border-[var(--border-subtle)] gap-[var(--space-2)] pr-[var(--space-4)] max-sm:flex-row max-sm:gap-[var(--space-6)] max-sm:overflow-x-auto max-sm:overflow-y-hidden max-sm:border-r-0 max-sm:border-b max-sm:pr-0"
|
|
3028
|
+
className: "group/tabs-list relative border-r border-[var(--border-subtle)] gap-[var(--space-2)] pr-[var(--space-4)] max-sm:flex-row max-sm:gap-[var(--space-6)] max-sm:overflow-x-auto max-sm:overflow-y-hidden max-sm:border-r-0 max-sm:border-b max-sm:pr-0"
|
|
3029
3029
|
},
|
|
3030
3030
|
{
|
|
3031
3031
|
variant: "contained",
|
|
@@ -3080,6 +3080,12 @@ var tabsTriggerVariants = cva8(
|
|
|
3080
3080
|
orientation: "horizontal",
|
|
3081
3081
|
className: "mx-[-2px] px-[2px] first:ml-0 last:mr-0 focus-visible:ring-0 focus-visible:inset-ring-2 focus-visible:inset-ring-[var(--focus-ring)]"
|
|
3082
3082
|
},
|
|
3083
|
+
// Once the list's indicator has measured the active trigger, it replaces the static ::after
|
|
3084
|
+
// underline. Before hydration (or without the indicator) the ::after stays.
|
|
3085
|
+
{
|
|
3086
|
+
variant: "line",
|
|
3087
|
+
className: "group-data-[indicator=ready]/tabs-list:after:hidden"
|
|
3088
|
+
},
|
|
3083
3089
|
{
|
|
3084
3090
|
variant: "line",
|
|
3085
3091
|
orientation: "vertical",
|
|
@@ -3092,6 +3098,35 @@ var tabsTriggerVariants = cva8(
|
|
|
3092
3098
|
}
|
|
3093
3099
|
}
|
|
3094
3100
|
);
|
|
3101
|
+
var tabsIndicatorVariants = cva8(
|
|
3102
|
+
[
|
|
3103
|
+
"pointer-events-none absolute invisible bg-[var(--text-primary)]",
|
|
3104
|
+
// transition-property stays none (duration alone would animate every property, visibility included)
|
|
3105
|
+
// until data-motion turns on the per-orientation transition below.
|
|
3106
|
+
"transition-none duration-[var(--dur-base)] ease-[var(--ease-standard)]",
|
|
3107
|
+
"group-data-[indicator=ready]/tabs-list:visible"
|
|
3108
|
+
].join(" "),
|
|
3109
|
+
{
|
|
3110
|
+
variants: {
|
|
3111
|
+
orientation: {
|
|
3112
|
+
horizontal: "bottom-[-1px] left-0 h-[2px] w-[var(--tabs-indicator-width)] [transform:translateX(var(--tabs-indicator-left))] motion-safe:data-[motion=on]:transition-[transform,width]",
|
|
3113
|
+
// Below `sm` the vertical list becomes a horizontal row, so the indicator follows the horizontal rule.
|
|
3114
|
+
vertical: [
|
|
3115
|
+
"max-sm:bottom-[-1px] max-sm:left-0 max-sm:h-[2px] max-sm:w-[var(--tabs-indicator-width)] max-sm:[transform:translateX(var(--tabs-indicator-left))] max-sm:motion-safe:data-[motion=on]:transition-[transform,width]",
|
|
3116
|
+
"sm:top-0 sm:right-[-1px] sm:h-[var(--tabs-indicator-height)] sm:w-[2px] sm:[transform:translateY(var(--tabs-indicator-top))] sm:motion-safe:data-[motion=on]:transition-[transform,height]"
|
|
3117
|
+
].join(" ")
|
|
3118
|
+
}
|
|
3119
|
+
},
|
|
3120
|
+
defaultVariants: {
|
|
3121
|
+
orientation: "horizontal"
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
);
|
|
3125
|
+
var tabsLabelReserveClassName = [
|
|
3126
|
+
"inline-flex flex-col",
|
|
3127
|
+
"before:invisible before:h-0 before:overflow-hidden before:font-medium before:content-[attr(data-label)]",
|
|
3128
|
+
"after:invisible after:h-0 after:overflow-hidden after:font-bold after:content-[attr(data-label)]"
|
|
3129
|
+
].join(" ");
|
|
3095
3130
|
var tabsBadgeVariants = cva8(
|
|
3096
3131
|
[
|
|
3097
3132
|
"inline-flex h-[18px] min-w-[18px] items-center justify-center",
|
|
@@ -3106,6 +3141,62 @@ var tabsBadgeVariants = cva8(
|
|
|
3106
3141
|
"group-data-[state=active]:border-[var(--border-strong)]"
|
|
3107
3142
|
].join(" ")
|
|
3108
3143
|
);
|
|
3144
|
+
function useTabsIndicator(enabled, activeKey, tabsKey, listRef, indicatorRef) {
|
|
3145
|
+
const placedRef = React17.useRef(null);
|
|
3146
|
+
const previousKeyRef = React17.useRef(null);
|
|
3147
|
+
const place = React17.useCallback(
|
|
3148
|
+
(animate) => {
|
|
3149
|
+
const list = listRef.current;
|
|
3150
|
+
const indicator = indicatorRef.current;
|
|
3151
|
+
if (!list || !indicator) return;
|
|
3152
|
+
const trigger = list.querySelector(':scope > [data-slot="tabs-trigger"][data-state="active"]');
|
|
3153
|
+
if (!trigger) {
|
|
3154
|
+
delete list.dataset.indicator;
|
|
3155
|
+
placedRef.current = null;
|
|
3156
|
+
return;
|
|
3157
|
+
}
|
|
3158
|
+
const { offsetLeft, offsetWidth, offsetTop, offsetHeight } = trigger;
|
|
3159
|
+
const placed = `${offsetLeft} ${offsetWidth} ${offsetTop} ${offsetHeight}`;
|
|
3160
|
+
if (placed === placedRef.current) return;
|
|
3161
|
+
placedRef.current = placed;
|
|
3162
|
+
if (animate && list.dataset.indicator === "ready") indicator.dataset.motion = "on";
|
|
3163
|
+
else delete indicator.dataset.motion;
|
|
3164
|
+
indicator.style.setProperty("--tabs-indicator-left", `${offsetLeft}px`);
|
|
3165
|
+
indicator.style.setProperty("--tabs-indicator-width", `${offsetWidth}px`);
|
|
3166
|
+
indicator.style.setProperty("--tabs-indicator-top", `${offsetTop}px`);
|
|
3167
|
+
indicator.style.setProperty("--tabs-indicator-height", `${offsetHeight}px`);
|
|
3168
|
+
list.dataset.indicator = "ready";
|
|
3169
|
+
},
|
|
3170
|
+
[listRef, indicatorRef]
|
|
3171
|
+
);
|
|
3172
|
+
React17.useLayoutEffect(() => {
|
|
3173
|
+
if (!enabled) {
|
|
3174
|
+
placedRef.current = null;
|
|
3175
|
+
previousKeyRef.current = null;
|
|
3176
|
+
return;
|
|
3177
|
+
}
|
|
3178
|
+
const previousKey = previousKeyRef.current;
|
|
3179
|
+
previousKeyRef.current = activeKey;
|
|
3180
|
+
place(previousKey !== null && previousKey !== activeKey);
|
|
3181
|
+
}, [enabled, activeKey, tabsKey, place]);
|
|
3182
|
+
React17.useEffect(() => {
|
|
3183
|
+
const list = listRef.current;
|
|
3184
|
+
if (!enabled || !list) return;
|
|
3185
|
+
let cancelled = false;
|
|
3186
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => place(false));
|
|
3187
|
+
if (observer) {
|
|
3188
|
+
observer.observe(list);
|
|
3189
|
+
list.querySelectorAll(':scope > [data-slot="tabs-trigger"]').forEach((trigger) => observer.observe(trigger));
|
|
3190
|
+
}
|
|
3191
|
+
document.fonts?.ready.then(() => {
|
|
3192
|
+
if (!cancelled) place(false);
|
|
3193
|
+
});
|
|
3194
|
+
return () => {
|
|
3195
|
+
cancelled = true;
|
|
3196
|
+
observer?.disconnect();
|
|
3197
|
+
};
|
|
3198
|
+
}, [enabled, tabsKey, place, listRef]);
|
|
3199
|
+
}
|
|
3109
3200
|
function formatTabBadge(value) {
|
|
3110
3201
|
return value > 99 ? "99+" : String(value);
|
|
3111
3202
|
}
|
|
@@ -3128,55 +3219,77 @@ var Tabs = React17.forwardRef(
|
|
|
3128
3219
|
orientation = "horizontal",
|
|
3129
3220
|
variant = "line",
|
|
3130
3221
|
...props
|
|
3131
|
-
}, ref) =>
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3222
|
+
}, ref) => {
|
|
3223
|
+
const listRef = React17.useRef(null);
|
|
3224
|
+
const indicatorRef = React17.useRef(null);
|
|
3225
|
+
const isLine = variant === "line";
|
|
3226
|
+
const tabsKey = tabs.map((tab) => tab.key).join("\0");
|
|
3227
|
+
useTabsIndicator(isLine, activeKey, tabsKey, listRef, indicatorRef);
|
|
3228
|
+
return /* @__PURE__ */ jsxs17(
|
|
3229
|
+
TabsPrimitive.Root,
|
|
3230
|
+
{
|
|
3231
|
+
ref,
|
|
3232
|
+
"data-slot": "tabs",
|
|
3233
|
+
value: activeKey,
|
|
3234
|
+
onValueChange: onChange,
|
|
3235
|
+
orientation,
|
|
3236
|
+
className: cn(tabsRootVariants({ orientation }), className),
|
|
3237
|
+
...props,
|
|
3238
|
+
children: [
|
|
3239
|
+
/* @__PURE__ */ jsxs17(
|
|
3240
|
+
TabsPrimitive.List,
|
|
3241
|
+
{
|
|
3242
|
+
ref: listRef,
|
|
3243
|
+
"data-slot": "tabs-list",
|
|
3244
|
+
"data-variant": variant,
|
|
3245
|
+
className: cn(tabsListVariants({ variant, orientation }), listClassName),
|
|
3246
|
+
children: [
|
|
3247
|
+
tabs.map((tab) => /* @__PURE__ */ jsxs17(
|
|
3248
|
+
TabsPrimitive.Trigger,
|
|
3249
|
+
{
|
|
3250
|
+
id: getTabId(baseId, tab.key),
|
|
3251
|
+
value: tab.key,
|
|
3252
|
+
disabled: tab.disabled,
|
|
3253
|
+
"aria-controls": getPanelId(baseId, tab.key),
|
|
3254
|
+
"data-slot": "tabs-trigger",
|
|
3255
|
+
"data-variant": variant,
|
|
3256
|
+
className: cn("group", tabsTriggerVariants({ variant, orientation }), triggerClassName),
|
|
3257
|
+
children: [
|
|
3258
|
+
isLine ? /* @__PURE__ */ jsx18("span", { "data-label": tab.label, className: tabsLabelReserveClassName, children: tab.label }) : /* @__PURE__ */ jsx18("span", { children: tab.label }),
|
|
3259
|
+
tab.badge !== void 0 && tab.badge > 0 ? /* @__PURE__ */ jsx18("span", { "aria-hidden": "true", "data-slot": "tabs-badge", className: tabsBadgeVariants(), children: formatTabBadge(tab.badge) }) : null,
|
|
3260
|
+
tab.disabled ? /* @__PURE__ */ jsx18(
|
|
3261
|
+
Lock,
|
|
3262
|
+
{
|
|
3263
|
+
"aria-hidden": "true",
|
|
3264
|
+
"data-slot": "tabs-disabled-icon",
|
|
3265
|
+
className: "size-[14px] shrink-0 text-text-disabled",
|
|
3266
|
+
strokeWidth: 2
|
|
3267
|
+
}
|
|
3268
|
+
) : null
|
|
3269
|
+
]
|
|
3270
|
+
},
|
|
3271
|
+
tab.key
|
|
3272
|
+
)),
|
|
3273
|
+
isLine ? /* @__PURE__ */ jsx18(
|
|
3274
|
+
"span",
|
|
3275
|
+
{
|
|
3276
|
+
ref: indicatorRef,
|
|
3277
|
+
"aria-hidden": "true",
|
|
3278
|
+
"data-slot": "tabs-indicator",
|
|
3279
|
+
className: tabsIndicatorVariants({ orientation }),
|
|
3280
|
+
onTransitionEnd: (event) => {
|
|
3281
|
+
if (event.target === event.currentTarget) delete event.currentTarget.dataset.motion;
|
|
3168
3282
|
}
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
)
|
|
3283
|
+
}
|
|
3284
|
+
) : null
|
|
3285
|
+
]
|
|
3286
|
+
}
|
|
3287
|
+
),
|
|
3288
|
+
children
|
|
3289
|
+
]
|
|
3290
|
+
}
|
|
3291
|
+
);
|
|
3292
|
+
}
|
|
3180
3293
|
);
|
|
3181
3294
|
Tabs.displayName = "Tabs";
|
|
3182
3295
|
var TabsContent = React17.forwardRef(({ className, tabKey, baseId, ...props }, ref) => /* @__PURE__ */ jsx18(
|
|
@@ -3559,6 +3672,7 @@ function useOverlayAction({
|
|
|
3559
3672
|
|
|
3560
3673
|
// src/lib/use-return-focus.ts
|
|
3561
3674
|
import * as React21 from "react";
|
|
3675
|
+
var closingOverlay = '[role="dialog"][data-state="closed"], [role="alertdialog"][data-state="closed"]';
|
|
3562
3676
|
function useReturnFocus() {
|
|
3563
3677
|
const returnTo = React21.useRef(null);
|
|
3564
3678
|
const onOpenAutoFocus = React21.useCallback((event) => {
|
|
@@ -3574,7 +3688,9 @@ function useReturnFocus() {
|
|
|
3574
3688
|
returnTo.current = null;
|
|
3575
3689
|
if (!target?.isConnected) return;
|
|
3576
3690
|
const active = document.activeElement;
|
|
3577
|
-
if (active instanceof HTMLElement && active !== document.body && active !== target)
|
|
3691
|
+
if (active instanceof HTMLElement && active !== document.body && active !== target && !active.closest(closingOverlay)) {
|
|
3692
|
+
return;
|
|
3693
|
+
}
|
|
3578
3694
|
event.preventDefault();
|
|
3579
3695
|
target.focus();
|
|
3580
3696
|
}, []);
|
|
@@ -10456,36 +10572,46 @@ function TreeView({
|
|
|
10456
10572
|
}
|
|
10457
10573
|
|
|
10458
10574
|
// src/components/branding/olun-logo.tsx
|
|
10459
|
-
import {
|
|
10460
|
-
|
|
10461
|
-
var
|
|
10575
|
+
import { OLUN_MASTER, OLUN_SYMBOL, OLUN_WORDMARK } from "@olundot/tokens/brand";
|
|
10576
|
+
import { Fragment as Fragment13, jsx as jsx64, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
10577
|
+
var ACCENT_FILL = "var(--accent-pop)";
|
|
10578
|
+
var INK = { color: "var(--text-primary)" };
|
|
10579
|
+
var INK_TIGHT = { ...INK, display: "block", overflow: "visible" };
|
|
10580
|
+
function symbolGeometry(size) {
|
|
10581
|
+
return size > OLUN_SYMBOL.smallMax ? OLUN_SYMBOL.large : OLUN_SYMBOL.small;
|
|
10582
|
+
}
|
|
10583
|
+
function SymbolCircles({ size }) {
|
|
10584
|
+
const { ring } = OLUN_SYMBOL;
|
|
10585
|
+
const g = symbolGeometry(size);
|
|
10586
|
+
return /* @__PURE__ */ jsxs50(Fragment13, { children: [
|
|
10587
|
+
/* @__PURE__ */ jsx64(
|
|
10588
|
+
"circle",
|
|
10589
|
+
{
|
|
10590
|
+
className: "olun-logo__ring",
|
|
10591
|
+
cx: ring.cx,
|
|
10592
|
+
cy: ring.cy,
|
|
10593
|
+
r: ring.r,
|
|
10594
|
+
stroke: "currentColor",
|
|
10595
|
+
strokeWidth: g.stroke,
|
|
10596
|
+
fill: "none"
|
|
10597
|
+
}
|
|
10598
|
+
),
|
|
10599
|
+
/* @__PURE__ */ jsx64("circle", { className: "olun-accent olun-logo__dot", cx: g.dot.cx, cy: g.dot.cy, r: g.dot.r, fill: ACCENT_FILL })
|
|
10600
|
+
] });
|
|
10601
|
+
}
|
|
10462
10602
|
function OlunSymbol({ size = 28, className }) {
|
|
10463
|
-
|
|
10464
|
-
return /* @__PURE__ */ jsxs50(
|
|
10603
|
+
return /* @__PURE__ */ jsx64(
|
|
10465
10604
|
"svg",
|
|
10466
10605
|
{
|
|
10467
10606
|
width: size,
|
|
10468
10607
|
height: size,
|
|
10469
|
-
viewBox:
|
|
10608
|
+
viewBox: `0 0 ${OLUN_SYMBOL.box} ${OLUN_SYMBOL.box}`,
|
|
10470
10609
|
fill: "none",
|
|
10471
10610
|
xmlns: "http://www.w3.org/2000/svg",
|
|
10472
10611
|
className,
|
|
10612
|
+
style: INK,
|
|
10473
10613
|
"aria-hidden": "true",
|
|
10474
|
-
children:
|
|
10475
|
-
/* @__PURE__ */ jsx64(
|
|
10476
|
-
"circle",
|
|
10477
|
-
{
|
|
10478
|
-
cx: "108",
|
|
10479
|
-
cy: "120",
|
|
10480
|
-
r: "60",
|
|
10481
|
-
stroke: "currentColor",
|
|
10482
|
-
strokeWidth: g.stroke,
|
|
10483
|
-
fill: "none",
|
|
10484
|
-
style: { color: "var(--text-primary)" }
|
|
10485
|
-
}
|
|
10486
|
-
),
|
|
10487
|
-
/* @__PURE__ */ jsx64("circle", { cx: g.dotX, cy: g.dotY, r: g.dotR, fill: "var(--accent-pop)" })
|
|
10488
|
-
]
|
|
10614
|
+
children: /* @__PURE__ */ jsx64(SymbolCircles, { size })
|
|
10489
10615
|
}
|
|
10490
10616
|
);
|
|
10491
10617
|
}
|
|
@@ -10495,33 +10621,61 @@ function OlunLogo({
|
|
|
10495
10621
|
showSymbol = true,
|
|
10496
10622
|
className
|
|
10497
10623
|
}) {
|
|
10624
|
+
if (!showSymbol) {
|
|
10625
|
+
const { full } = OLUN_WORDMARK;
|
|
10626
|
+
const height2 = fontSize * full.height / OLUN_WORDMARK.unitsPerEm;
|
|
10627
|
+
return /* @__PURE__ */ jsxs50(
|
|
10628
|
+
"svg",
|
|
10629
|
+
{
|
|
10630
|
+
width: height2 * full.width / full.height,
|
|
10631
|
+
height: height2,
|
|
10632
|
+
viewBox: full.viewBox,
|
|
10633
|
+
fill: "none",
|
|
10634
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
10635
|
+
className,
|
|
10636
|
+
style: INK_TIGHT,
|
|
10637
|
+
role: "img",
|
|
10638
|
+
"aria-label": "OLUN.",
|
|
10639
|
+
children: [
|
|
10640
|
+
/* @__PURE__ */ jsx64("path", { className: "olun-logo__wordmark", fill: "currentColor", d: full.letters }),
|
|
10641
|
+
/* @__PURE__ */ jsx64(
|
|
10642
|
+
"circle",
|
|
10643
|
+
{
|
|
10644
|
+
className: "olun-accent olun-logo__period",
|
|
10645
|
+
cx: full.period.cx,
|
|
10646
|
+
cy: full.period.cy,
|
|
10647
|
+
r: full.period.r,
|
|
10648
|
+
fill: ACCENT_FILL
|
|
10649
|
+
}
|
|
10650
|
+
)
|
|
10651
|
+
]
|
|
10652
|
+
}
|
|
10653
|
+
);
|
|
10654
|
+
}
|
|
10655
|
+
const layout = symbolSize > OLUN_SYMBOL.smallMax ? OLUN_MASTER.large : OLUN_MASTER.small;
|
|
10656
|
+
const height = symbolSize * layout.height / (OLUN_SYMBOL.box * layout.symbol.scale);
|
|
10498
10657
|
return /* @__PURE__ */ jsxs50(
|
|
10499
|
-
"
|
|
10658
|
+
"svg",
|
|
10500
10659
|
{
|
|
10660
|
+
width: height * layout.width / layout.height,
|
|
10661
|
+
height,
|
|
10662
|
+
viewBox: layout.viewBox,
|
|
10663
|
+
fill: "none",
|
|
10664
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
10501
10665
|
className,
|
|
10502
|
-
style:
|
|
10503
|
-
|
|
10504
|
-
|
|
10505
|
-
gap: "var(--space-3)"
|
|
10506
|
-
},
|
|
10666
|
+
style: INK_TIGHT,
|
|
10667
|
+
role: "img",
|
|
10668
|
+
"aria-label": "OLUN",
|
|
10507
10669
|
children: [
|
|
10508
|
-
|
|
10509
|
-
|
|
10510
|
-
"span",
|
|
10670
|
+
/* @__PURE__ */ jsx64(
|
|
10671
|
+
"g",
|
|
10511
10672
|
{
|
|
10512
|
-
|
|
10513
|
-
|
|
10514
|
-
|
|
10515
|
-
fontSize: `${fontSize}px`,
|
|
10516
|
-
letterSpacing: "-0.02em",
|
|
10517
|
-
color: "var(--text-primary)"
|
|
10518
|
-
},
|
|
10519
|
-
children: [
|
|
10520
|
-
"OLUN",
|
|
10521
|
-
!showSymbol && /* @__PURE__ */ jsx64("span", { style: { color: "var(--accent)" }, children: "." })
|
|
10522
|
-
]
|
|
10673
|
+
className: "olun-logo__symbol",
|
|
10674
|
+
transform: `translate(${layout.symbol.x} ${layout.symbol.y}) scale(${layout.symbol.scale})`,
|
|
10675
|
+
children: /* @__PURE__ */ jsx64(SymbolCircles, { size: symbolSize })
|
|
10523
10676
|
}
|
|
10524
|
-
)
|
|
10677
|
+
),
|
|
10678
|
+
/* @__PURE__ */ jsx64("path", { className: "olun-logo__wordmark", fill: "currentColor", d: layout.letters })
|
|
10525
10679
|
]
|
|
10526
10680
|
}
|
|
10527
10681
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olundot/ui",
|
|
3
|
-
"version": "0.20.0-next.
|
|
3
|
+
"version": "0.20.0-next.3",
|
|
4
4
|
"description": "OLUN. shared React UI components built on OLUN design tokens",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"lucide-react": "^1.8.0",
|
|
45
45
|
"radix-ui": "^1.4.3",
|
|
46
46
|
"tailwind-merge": "^3.5.0",
|
|
47
|
-
"@olundot/tokens": "^0.18.0-next.
|
|
47
|
+
"@olundot/tokens": "^0.18.0-next.1"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"react": ">=18",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"@types/node": "^24.10.0",
|
|
63
63
|
"@types/react": "^19.2.14",
|
|
64
64
|
"@types/react-dom": "^19.2.3",
|
|
65
|
+
"esbuild": "^0.27.7",
|
|
65
66
|
"jsdom": "^30.1.1",
|
|
66
67
|
"react": "^19.2.6",
|
|
67
68
|
"react-dom": "^19.2.6",
|