b44ui 0.0.7 → 0.0.8
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/example/pnpm-lock.yaml +8 -8
- package/example/src/App.tsx +7 -7
- package/index.tsx +89 -39
- package/package.json +3 -3
package/example/pnpm-lock.yaml
CHANGED
|
@@ -724,9 +724,9 @@ packages:
|
|
|
724
724
|
peerDependencies:
|
|
725
725
|
marked: '>=4 <18'
|
|
726
726
|
|
|
727
|
-
marked@
|
|
728
|
-
resolution: {integrity: sha512-
|
|
729
|
-
engines: {node: '>=
|
|
727
|
+
marked@17.0.4:
|
|
728
|
+
resolution: {integrity: sha512-NOmVMM+KAokHMvjWmC5N/ZOvgmSWuqJB8FoYI019j4ogb/PeRMKoKIjReZ2w3376kkA8dSJIP8uD993Kxc0iRQ==}
|
|
729
|
+
engines: {node: '>= 20'}
|
|
730
730
|
hasBin: true
|
|
731
731
|
|
|
732
732
|
ms@2.1.3:
|
|
@@ -1251,8 +1251,8 @@ snapshots:
|
|
|
1251
1251
|
dependencies:
|
|
1252
1252
|
clsx: 2.1.1
|
|
1253
1253
|
highlight.js: 11.11.1
|
|
1254
|
-
marked:
|
|
1255
|
-
marked-highlight: 2.2.3(marked@
|
|
1254
|
+
marked: 17.0.4
|
|
1255
|
+
marked-highlight: 2.2.3(marked@17.0.4)
|
|
1256
1256
|
react: 19.2.4
|
|
1257
1257
|
tailwind-merge: 3.5.0
|
|
1258
1258
|
|
|
@@ -1396,11 +1396,11 @@ snapshots:
|
|
|
1396
1396
|
dependencies:
|
|
1397
1397
|
'@jridgewell/sourcemap-codec': 1.5.5
|
|
1398
1398
|
|
|
1399
|
-
marked-highlight@2.2.3(marked@
|
|
1399
|
+
marked-highlight@2.2.3(marked@17.0.4):
|
|
1400
1400
|
dependencies:
|
|
1401
|
-
marked:
|
|
1401
|
+
marked: 17.0.4
|
|
1402
1402
|
|
|
1403
|
-
marked@
|
|
1403
|
+
marked@17.0.4: {}
|
|
1404
1404
|
|
|
1405
1405
|
ms@2.1.3: {}
|
|
1406
1406
|
|
package/example/src/App.tsx
CHANGED
|
@@ -76,22 +76,22 @@ export default function YACS() {
|
|
|
76
76
|
<Grid cols={3} cn="h-full">
|
|
77
77
|
|
|
78
78
|
{/* calendar */}
|
|
79
|
-
<Card
|
|
79
|
+
<Card cnIgnoreWrongUsage="col-span-2 row-span-1 p-4 overflow-hidden flex flex-col">
|
|
80
80
|
<D cn="grid flex-1" style={{ gridTemplateColumns: `60px repeat(5, 1fr)` }}>
|
|
81
81
|
{/* hour labels */}
|
|
82
|
-
<D
|
|
82
|
+
<D cnIgnoreWrongUsage="flex flex-col justify-between text-sm text-zinc-500 pr-2">
|
|
83
83
|
{hours.map(h => <span key={h}>{h > 12 ? h - 12 : h}{h >= 12 ? 'pm' : 'am'}</span>)}
|
|
84
84
|
</D>
|
|
85
85
|
{/* day columns */}
|
|
86
|
-
{days.map(day => <D key={day}
|
|
87
|
-
<Muted
|
|
86
|
+
{days.map(day => <D key={day} cnIgnoreWrongUsage="relative border-l border-zinc-800">
|
|
87
|
+
<Muted cnIgnoreWrongUsage="text-center block text-sm mb-1">{day}</Muted>
|
|
88
88
|
{/* hour gridlines */}
|
|
89
|
-
{hours.map(h => <D key={h}
|
|
89
|
+
{hours.map(h => <D key={h} cnIgnoreWrongUsage="border-t border-zinc-800/50 left-0 right-0 absolute" style={{ top: `${h*8}%` }} />)}
|
|
90
90
|
{/* events */}
|
|
91
91
|
{events.filter(e => e.meeting.day === day).map((e, i) => {
|
|
92
92
|
const top = ((e.meeting.start - 540) / (13 * 60)) * 100
|
|
93
93
|
const height = ((e.meeting.end - e.meeting.start) / (13 * 60)) * 100
|
|
94
|
-
return <D key={i}
|
|
94
|
+
return <D key={i} cnIgnoreWrongUsage={`absolute left-0.5 right-0.5 rounded text-sm px-1 text-white ${colors[e.colorIdx % colors.length]}`}
|
|
95
95
|
style={{ top: `${top}%`, height: `${height}%` }}>
|
|
96
96
|
{e.code}
|
|
97
97
|
</D>
|
|
@@ -108,7 +108,7 @@ export default function YACS() {
|
|
|
108
108
|
<Input grow placeholder="search..." value={query} onChange={e => setQuery(e.target.value)} />
|
|
109
109
|
<Select><option>2026W</option><option>2026S</option></Select>
|
|
110
110
|
</Row>
|
|
111
|
-
<D
|
|
111
|
+
<D cnIgnoreWrongUsage="space-y-3 max-h-48 overflow-y-auto flex-row">
|
|
112
112
|
{results.map(c => <Btn key={c.code} click={() => addCourse(c)} grow>
|
|
113
113
|
{c.code} — {c.name}
|
|
114
114
|
</Btn>)}
|
package/index.tsx
CHANGED
|
@@ -26,11 +26,15 @@ const colorCn = (c: Color) => colorMap[c]
|
|
|
26
26
|
|
|
27
27
|
export const CN = (...inputs: ClassValue[]) => twMerge(clsx(inputs))
|
|
28
28
|
|
|
29
|
+
const warnCn = (cn: any) => typeof cn === 'string' && cn.length > 24 && console.warn(`long cn detected (${cn.length} chars). please avoid using cn. you SHOULD use b44ui builtins instead. you SHOULD NOT use cn to add unnecessary visual enhancements. you MUST NOT have long cns. if you choose to ignore these requirements (ie. because you cannot achieve this otherwise) you MUST instead use <... cnIgnoreWrongUsage="styles..">\n cn="${cn}"`)
|
|
30
|
+
const rcn = ({ cn, cnIgnoreWrongUsage }: DProps) => { warnCn(cn); return cn ?? cnIgnoreWrongUsage }
|
|
31
|
+
|
|
29
32
|
const sc = (n?: number) => n !== undefined ? n * 4 : undefined // tailwind scale -> px
|
|
30
33
|
|
|
31
34
|
export type DProps = {
|
|
32
35
|
children?: ReactNode
|
|
33
36
|
cn?: any
|
|
37
|
+
cnIgnoreWrongUsage?: any
|
|
34
38
|
style?: React.CSSProperties
|
|
35
39
|
grow?: boolean
|
|
36
40
|
gap?: number
|
|
@@ -44,83 +48,129 @@ const dStyle = ({ gap, p, style }: DProps): React.CSSProperties | undefined => {
|
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
export const D = (props: DProps) =>
|
|
47
|
-
<div className={CN(props.cn, props.grow && "flex-1")} style={dStyle(props)}>{props.children}</div>
|
|
51
|
+
<div className={CN(props.cn ?? props.cnIgnoreWrongUsage, props.grow && "flex-1")} style={dStyle(props)}>{props.children}</div>
|
|
48
52
|
|
|
49
|
-
export const App = (
|
|
53
|
+
export const App = (props: DProps & { center?: boolean, width?: number }) => {
|
|
54
|
+
const { children, center = true, width, gap, p } = props
|
|
55
|
+
const c = rcn(props)
|
|
50
56
|
const inner = Children.map(children, c => typeof c == 'string' ? <Md>{c.trim()}</Md> : c)
|
|
51
|
-
return <D cn={
|
|
57
|
+
return <D cn={CN("min-h-screen w-full bg-[#111] text-[#eee] font-[Inter]", center && "flex justify-center items-center", c)} gap={gap} p={p}>
|
|
52
58
|
{center ? <div className="max-w-full px-5 py-10 space-y-5 *:mx-auto" style={{ width }}>{inner}</div> : inner}
|
|
53
59
|
</D>
|
|
54
60
|
}
|
|
55
61
|
|
|
56
|
-
export const Centered = (
|
|
57
|
-
|
|
62
|
+
export const Centered = (props: DProps & { width?: number }) => {
|
|
63
|
+
const { children, grow, gap, p, width = 700 } = props
|
|
64
|
+
return <D cn={CN("mx-auto max-w-full px-6", rcn(props))} grow={grow} gap={gap} p={p} style={{ width }}>{children}</D>
|
|
65
|
+
}
|
|
58
66
|
|
|
59
|
-
export const Block = (
|
|
60
|
-
|
|
67
|
+
export const Block = (props: DProps & { label?: ReactNode, row?: boolean, dashed?: boolean }) => {
|
|
68
|
+
const { label, children, row, dashed, grow, gap, p } = props
|
|
69
|
+
return <D cn={CN("rounded flex flex-col items-center", dashed && "border border-dashed border-zinc-700", rcn(props))} grow={grow} gap={gap ?? 4} p={p ?? 4}>
|
|
61
70
|
{label && <span className="opacity-75">{label}</span>}
|
|
62
71
|
<div className={CN(row ? "flex-row" : "flex-col", "flex items-center")} style={{ gap: sc(gap ?? 4) }}>{children}</div>
|
|
63
72
|
</D>
|
|
73
|
+
}
|
|
64
74
|
|
|
65
|
-
export const BlockSm = (
|
|
66
|
-
|
|
75
|
+
export const BlockSm = (props: DProps & { dashed?: boolean }) => {
|
|
76
|
+
const { children, dashed, grow, gap, p } = props
|
|
77
|
+
return <D cn={CN("rounded text-sm", dashed && "border border-dashed border-zinc-700", rcn(props))} grow={grow} gap={gap} p={p ?? 2}
|
|
67
78
|
style={{ paddingLeft: sc(3), paddingRight: sc(3) }}>{children}</D>
|
|
79
|
+
}
|
|
68
80
|
|
|
69
|
-
export const Chip = (
|
|
70
|
-
|
|
81
|
+
export const Chip = (props: DProps & { click?: () => void }) => {
|
|
82
|
+
const { children, click } = props
|
|
83
|
+
return <span className={CN("bg-zinc-800 rounded px-2 py-0.5 text-xs", click && "cursor-pointer hover:bg-zinc-700", rcn(props))}
|
|
71
84
|
onClick={click}>{children}</span>
|
|
85
|
+
}
|
|
72
86
|
|
|
73
|
-
export const Card = (
|
|
74
|
-
|
|
87
|
+
export const Card = (props: DProps) => {
|
|
88
|
+
const { children, grow, gap, p } = props
|
|
89
|
+
return <D cn={CN("rounded border border-zinc-700 bg-zinc-900", rcn(props))} grow={grow} gap={gap ?? 4} p={p ?? 4}
|
|
75
90
|
style={{ display: 'flex', flexDirection: 'column' }}>{children}</D>
|
|
91
|
+
}
|
|
76
92
|
|
|
77
|
-
export const Col = (
|
|
78
|
-
|
|
93
|
+
export const Col = (props: DProps) => {
|
|
94
|
+
const { children, grow, gap, p } = props
|
|
95
|
+
return <D cn={CN("flex flex-col", rcn(props))} grow={grow} gap={gap ?? 4} p={p}>{children}</D>
|
|
96
|
+
}
|
|
79
97
|
|
|
80
|
-
export const Popover = (
|
|
98
|
+
export const Popover = (props: DProps & { text: ReactNode, color?: Color }) => {
|
|
99
|
+
const { children, text, color } = props
|
|
100
|
+
const c = rcn(props)
|
|
81
101
|
const [open, setOpen] = useState(false)
|
|
82
102
|
return <span className="relative inline-block" onMouseEnter={() => setOpen(true)} onMouseLeave={() => setOpen(false)}>
|
|
83
|
-
<span className={CN("cursor-pointer", color && tintCn(color), color && "border-b-2",
|
|
103
|
+
<span className={CN("cursor-pointer", color && tintCn(color), color && "border-b-2", c)}>{children}</span>
|
|
84
104
|
{open && <div className="absolute left-0 top-full z-10 mt-1">
|
|
85
105
|
<Card cn="w-64 shadow-lg text-sm" p={3}>{text}</Card>
|
|
86
106
|
</div>}
|
|
87
107
|
</span>
|
|
88
108
|
}
|
|
89
109
|
|
|
90
|
-
export const Muted = (
|
|
91
|
-
|
|
110
|
+
export const Muted = (props: DProps) => {
|
|
111
|
+
const { children, grow } = props
|
|
112
|
+
return <span className={CN("text-sm text-zinc-400", grow && "flex-1", rcn(props))}>{children}</span>
|
|
113
|
+
}
|
|
92
114
|
|
|
93
|
-
export const Btn = ({ children,
|
|
94
|
-
|
|
95
|
-
|
|
115
|
+
export const Btn = ({ children, grow, gap, p, click, color, ghost, sm, ...rest }: DProps & { click?: () => void, color?: Color, ghost?: boolean, sm?: boolean } & React.ButtonHTMLAttributes<HTMLButtonElement>) => {
|
|
116
|
+
const c = rcn(rest as DProps)
|
|
117
|
+
return <button className={CN("rounded cursor-pointer", sm ? "px-3 py-1 text-xs" : "px-4 py-2 text-sm",
|
|
118
|
+
ghost ? "bg-transparent text-zinc-400 hover:bg-zinc-800" : color ? colorCn(color) : "bg-zinc-800 hover:bg-zinc-700", grow && "flex-1", c)}
|
|
96
119
|
style={dStyle({ gap, p })} onClick={click} {...rest}>{children}</button>
|
|
120
|
+
}
|
|
97
121
|
|
|
98
|
-
export const Tint = (
|
|
99
|
-
|
|
122
|
+
export const Tint = (props: DProps & { color: Color }) => {
|
|
123
|
+
const { children, color, grow, gap, p } = props
|
|
124
|
+
return <D cn={CN("rounded text-sm", tintCn(color), rcn(props))} grow={grow} gap={gap} p={p ?? 3}>{children}</D>
|
|
125
|
+
}
|
|
100
126
|
|
|
101
|
-
export const Row = (
|
|
102
|
-
|
|
127
|
+
export const Row = (props: DProps & { ratio?: number, align?: 'mid' | 'start' | 'end' }) => {
|
|
128
|
+
const { children, ratio, align, grow, gap, p } = props
|
|
129
|
+
return <div className={CN("flex items-center justify-center", align === 'mid' && "justify-between", align == 'end' && "justify-end", align == 'start' && "justify-start", grow && "flex-1", rcn(props))}
|
|
103
130
|
style={{ gap: sc(gap ?? 4), ...(p !== undefined && { padding: sc(p) }), ...(ratio ? { width: `${ratio * 100}%` } : {}) }}>{children}</div>
|
|
131
|
+
}
|
|
104
132
|
|
|
105
|
-
export const Toolbar = (
|
|
106
|
-
|
|
133
|
+
export const Toolbar = (props: DProps) => {
|
|
134
|
+
const { children, gap, p } = props
|
|
135
|
+
return <Row cn={CN("border-b border-zinc-700", rcn(props))} gap={gap} p={p ?? 2} align="mid">{children}</Row>
|
|
136
|
+
}
|
|
107
137
|
|
|
108
|
-
export const Modal = (
|
|
109
|
-
|
|
110
|
-
|
|
138
|
+
export const Modal = (props: DProps & { open: boolean }) => {
|
|
139
|
+
const { children, open, gap, p } = props
|
|
140
|
+
return open ? <div className="fixed inset-0 flex items-center justify-center bg-black/50 z-50">
|
|
141
|
+
<Card cn={CN("max-h-[80vh] overflow-y-auto w-lg", rcn(props))} gap={gap} p={p}>{children}</Card>
|
|
111
142
|
</div> : null
|
|
143
|
+
}
|
|
112
144
|
|
|
113
|
-
export const Input = ({ cn, grow, ...rest }:
|
|
114
|
-
|
|
145
|
+
export const Input = ({ cn, cnIgnoreWrongUsage, grow, ...rest }: DProps & React.InputHTMLAttributes<HTMLInputElement>) => {
|
|
146
|
+
const c = rcn({ cn, cnIgnoreWrongUsage })
|
|
147
|
+
return <input className={CN("rounded bg-zinc-800 border border-zinc-700 px-3 py-2 text-sm outline-none", grow && "flex-1", c)} {...rest} />
|
|
148
|
+
}
|
|
115
149
|
|
|
116
|
-
export const Textarea = ({ cn, grow, ...rest }:
|
|
117
|
-
|
|
150
|
+
export const Textarea = ({ cn, cnIgnoreWrongUsage, grow, ...rest }: DProps & React.TextareaHTMLAttributes<HTMLTextAreaElement>) => {
|
|
151
|
+
const c = rcn({ cn, cnIgnoreWrongUsage })
|
|
152
|
+
return <textarea className={CN("rounded bg-zinc-800 border border-zinc-700 px-3 py-2 text-sm outline-none w-full", grow && "flex-1", c)} {...rest} />
|
|
153
|
+
}
|
|
118
154
|
|
|
119
|
-
export const Select = ({ cn, grow, ...rest }:
|
|
120
|
-
|
|
155
|
+
export const Select = ({ cn, cnIgnoreWrongUsage, grow, ...rest }: DProps & React.SelectHTMLAttributes<HTMLSelectElement>) => {
|
|
156
|
+
const c = rcn({ cn, cnIgnoreWrongUsage })
|
|
157
|
+
return <select className={CN("rounded bg-zinc-800 border border-zinc-700 px-3 py-2 text-sm outline-none cursor-pointer", grow && "flex-1", c)} {...rest} />
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export const Grid = (props: DProps & { cols?: number }) => {
|
|
161
|
+
const { children, cols, grow, gap, p } = props
|
|
162
|
+
return <D cn={CN("grid ui-grid", rcn(props))} grow={grow} p={p} style={{ gap: sc(gap ?? 4), '--cols': cols ?? Children.count(children) } as React.CSSProperties}>{children}</D>
|
|
163
|
+
}
|
|
121
164
|
|
|
122
|
-
export const
|
|
123
|
-
|
|
165
|
+
export const Code = (props: DProps & { highlight?: string }) => {
|
|
166
|
+
const { children, highlight } = props
|
|
167
|
+
const c = rcn(props)
|
|
168
|
+
const html = useMemo(() => highlight ? hljs.highlight(children as string, { language: highlight }).value : '', [children, highlight])
|
|
169
|
+
if (highlight) return <pre className={CN("rounded bg-zinc-900 border border-zinc-700 p-3 text-sm overflow-x-auto", c)}>
|
|
170
|
+
<code className={`hljs language-${highlight}`} dangerouslySetInnerHTML={{ __html: html }} />
|
|
171
|
+
</pre>
|
|
172
|
+
return <code className={CN("bg-zinc-800 rounded px-1.5 py-0.5 text-sm font-mono", c)}>{children}</code>
|
|
173
|
+
}
|
|
124
174
|
|
|
125
175
|
const marked = new Marked(markedHighlight({ langPrefix: "hljs language-", highlight: c => hljs.highlightAuto(c).value }))
|
|
126
176
|
export const Md = ({ children, className }: { children: string, className?: string }) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "b44ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "npm run dev --prefix example"
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"clsx": "^2.1.1",
|
|
14
14
|
"highlight.js": "^11.11.0",
|
|
15
|
-
"marked": "^
|
|
16
|
-
"marked-highlight": "^2.2.
|
|
15
|
+
"marked": "^17.0.0",
|
|
16
|
+
"marked-highlight": "^2.2.3",
|
|
17
17
|
"tailwind-merge": "^3.0.0"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|