@skalfa/skalfa-app 1.0.3 → 1.0.6

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.
Files changed (90) hide show
  1. package/.env.example +8 -16
  2. package/app/auth/edit/page.tsx +1 -1
  3. package/app/auth/login/page.tsx +1 -1
  4. package/app/auth/me/page.tsx +1 -1
  5. package/app/auth/register/page.tsx +1 -1
  6. package/app/auth/verify/page.tsx +1 -1
  7. package/app/dashboard/layout.tsx +2 -2
  8. package/app/dashboard/page.tsx +1 -1
  9. package/app/index.ts +1 -0
  10. package/app/layout.tsx +2 -4
  11. package/app/page.tsx +2 -2
  12. package/bun.lock +7 -2
  13. package/components/index.ts +1 -3
  14. package/package.json +10 -7
  15. package/styles/components.css +1392 -0
  16. package/styles/globals.css +40 -175
  17. package/styles/utilities.css +37 -0
  18. package/tsconfig.json +4 -2
  19. package/utils/commands/skalfa.ts +1 -1
  20. package/components/base.components/accordion/Accordion.component.tsx +0 -82
  21. package/components/base.components/breadcrumb/Breadcrumb.component.tsx +0 -80
  22. package/components/base.components/button/Button.component.tsx +0 -91
  23. package/components/base.components/button/IconButton.component.tsx +0 -88
  24. package/components/base.components/button/button.decorate.ts +0 -82
  25. package/components/base.components/card/AlertCard.component.tsx +0 -69
  26. package/components/base.components/card/Card.component.tsx +0 -25
  27. package/components/base.components/card/DashboardCard.component.tsx +0 -44
  28. package/components/base.components/card/GalleryCard.component.tsx +0 -50
  29. package/components/base.components/card/ProductCard.component.tsx +0 -65
  30. package/components/base.components/card/ProfileCard.component.tsx +0 -71
  31. package/components/base.components/carousel/Carousel.component.tsx +0 -113
  32. package/components/base.components/chip/Chip.component.tsx +0 -39
  33. package/components/base.components/document/DocumentViewer.component.tsx +0 -164
  34. package/components/base.components/document/ExportExcel.component.tsx +0 -340
  35. package/components/base.components/document/ImportExcel.component.tsx +0 -315
  36. package/components/base.components/document/PrintTable.component.tsx +0 -204
  37. package/components/base.components/document/RenderPDF.component.tsx +0 -416
  38. package/components/base.components/index.ts +0 -85
  39. package/components/base.components/input/Checkbox.component.tsx +0 -109
  40. package/components/base.components/input/Input.component.tsx +0 -332
  41. package/components/base.components/input/InputCheckbox.component.tsx +0 -174
  42. package/components/base.components/input/InputCurrency.component.tsx +0 -163
  43. package/components/base.components/input/InputDate.component.tsx +0 -352
  44. package/components/base.components/input/InputDatetime.component.tsx +0 -260
  45. package/components/base.components/input/InputDocument.component.tsx +0 -352
  46. package/components/base.components/input/InputImage.component.tsx +0 -533
  47. package/components/base.components/input/InputMap.component.tsx +0 -318
  48. package/components/base.components/input/InputNumber.component.tsx +0 -192
  49. package/components/base.components/input/InputOtp.component.tsx +0 -169
  50. package/components/base.components/input/InputPassword.component.tsx +0 -236
  51. package/components/base.components/input/InputRadio.component.tsx +0 -175
  52. package/components/base.components/input/InputTime.component.tsx +0 -276
  53. package/components/base.components/input/InputValues.component.tsx +0 -68
  54. package/components/base.components/input/Radio.component.tsx +0 -102
  55. package/components/base.components/input/Select.component.tsx +0 -541
  56. package/components/base.components/modal/BottomSheet.component.tsx +0 -246
  57. package/components/base.components/modal/FloatingPage.component.tsx +0 -104
  58. package/components/base.components/modal/Modal.component.tsx +0 -96
  59. package/components/base.components/modal/ModalConfirm.component.tsx +0 -218
  60. package/components/base.components/modal/Toast.component.tsx +0 -126
  61. package/components/base.components/nav/Bottombar.component.tsx +0 -116
  62. package/components/base.components/nav/Footer.component.tsx +0 -144
  63. package/components/base.components/nav/Headbar.component.tsx +0 -104
  64. package/components/base.components/nav/Navbar.component.tsx +0 -100
  65. package/components/base.components/nav/Sidebar.component.tsx +0 -301
  66. package/components/base.components/nav/Tabbar.component.tsx +0 -60
  67. package/components/base.components/nav/Wizard.component.tsx +0 -73
  68. package/components/base.components/supervision/FormSupervision.component.tsx +0 -434
  69. package/components/base.components/supervision/TableSupervision.component.tsx +0 -697
  70. package/components/base.components/table/ControlBar.component.tsx +0 -497
  71. package/components/base.components/table/FilterComponent.tsx +0 -518
  72. package/components/base.components/table/Pagination.component.tsx +0 -159
  73. package/components/base.components/table/Table.component.tsx +0 -469
  74. package/components/base.components/typography/TypographyArticle.component.tsx +0 -26
  75. package/components/base.components/typography/TypographyColumn.component.tsx +0 -20
  76. package/components/base.components/typography/TypographyContent.component.tsx +0 -20
  77. package/components/base.components/typography/TypographyTips.component.tsx +0 -20
  78. package/components/base.components/wrap/Draggable.component.tsx +0 -303
  79. package/components/base.components/wrap/IDBProvider.tsx +0 -12
  80. package/components/base.components/wrap/Image.component.tsx +0 -10
  81. package/components/base.components/wrap/OutsideClick.component.tsx +0 -48
  82. package/components/base.components/wrap/ScrollContainer.component.tsx +0 -104
  83. package/components/base.components/wrap/ShortcutProvider.tsx +0 -57
  84. package/components/base.components/wrap/Swipe.component.tsx +0 -93
  85. package/components/construct.components/example.tsx +0 -1
  86. package/components/construct.components/index.ts +0 -5
  87. package/components/structure.components/example.tsx +0 -1
  88. package/components/structure.components/index.ts +0 -5
  89. package/schema/idb/app.schema.ts +0 -9
  90. package/schema/index.ts +0 -5
@@ -1,416 +0,0 @@
1
- "use client"
2
-
3
- import { PDFDocument, StandardFonts, PDFPage, rgb } from 'pdf-lib'
4
- import { useEffect, useRef } from 'react'
5
-
6
- export const PaperSize = {
7
- LETTER: { width: 612, height: 792 },
8
- A4: { width: 595, height: 842 },
9
- }
10
-
11
- export type RenderPDFProps = {
12
- content: PageSchema[]
13
- }
14
-
15
- export type PageSchema = {
16
- page: {
17
- size?: keyof typeof PaperSize | { width: number; height: number }
18
- margin?: number
19
- content: NodeSchema[]
20
- }
21
- }
22
-
23
- export type Style = {
24
- width?: number
25
- height?: number
26
-
27
- padding?: number
28
- paddingTop?: number
29
- paddingRight?: number
30
- paddingBottom?: number
31
- paddingLeft?: number
32
- paddingX?: number
33
- paddingY?: number
34
-
35
- marginTop?: number
36
- marginBottom?: number
37
-
38
- fontSize?: number
39
- fontWeight?: "normal" | "bold"
40
- lineHeight?: number
41
- letterSpacing?: number
42
- color?: string
43
- opacity?: number
44
- align?: "left" | "center" | "right"
45
- textTransform?: "uppercase" | "lowercase" | "capitalize"
46
-
47
- backgroundColor?: string
48
- borderColor?: string
49
- borderWidth?: number
50
-
51
- underline?: boolean
52
-
53
- textAlign?: "left" | "center" | "right"
54
- }
55
-
56
- export type NodeSchema =
57
- | { type: "view"; style?: Style; content: NodeSchema[] }
58
- | { type: "text"; content: string; style?: Style }
59
- | { type: "image"; src: string | Uint8Array | ArrayBuffer; style?: Style }
60
- | { type: "table"; content: NodeSchema[] }
61
- | { type: "tr"; content: NodeSchema[], style?: Style }
62
- | { type: 'td' | 'th'; content: NodeSchema[] | string; style?: Style }
63
-
64
- // ==================================================
65
- // Layout Context
66
- // ==================================================
67
-
68
- class LayoutContext {
69
- x: number
70
- y: number
71
- constructor(
72
- public width: number,
73
- public height: number,
74
- public margin: number
75
- ) {
76
- this.x = margin
77
- this.y = height - margin
78
- }
79
-
80
- needBreak(h: number) {
81
- return this.y - h < this.margin
82
- }
83
-
84
- reset() {
85
- this.x = this.margin
86
- this.y = this.height - this.margin
87
- }
88
- }
89
-
90
- // ==================================================
91
- // Helpers
92
- // ==================================================
93
-
94
- function resolvePadding(style?: Style) {
95
- const p = style?.padding ?? 0
96
- const px = style?.paddingX ?? p
97
- const py = style?.paddingY ?? p
98
-
99
- return {
100
- top: style?.paddingTop ?? py,
101
- bottom: style?.paddingBottom ?? py,
102
- left: style?.paddingLeft ?? px,
103
- right: style?.paddingRight ?? px,
104
- }
105
- }
106
-
107
- function resolveText(text: string, style?: Style) {
108
- if (!style?.textTransform) return text
109
- if (style.textTransform === "uppercase") return text.toUpperCase()
110
- if (style.textTransform === "lowercase") return text.toLowerCase()
111
- if (style.textTransform === "capitalize")
112
- return text.replace(/\b\w/g, c => c.toUpperCase())
113
- return text
114
- }
115
-
116
- function hexToRgb(hex?: string) {
117
- if (!hex) return undefined
118
- const h = hex.replace("#", "")
119
- return rgb(
120
- parseInt(h.slice(0, 2), 16) / 255,
121
- parseInt(h.slice(2, 4), 16) / 255,
122
- parseInt(h.slice(4, 6), 16) / 255
123
- )
124
- }
125
-
126
- async function embedImage(pdf: PDFDocument, bytes: Uint8Array | ArrayBuffer) {
127
- const data = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes)
128
- try {
129
- return await pdf.embedPng(data)
130
- } catch {
131
- return await pdf.embedJpg(data)
132
- }
133
- }
134
-
135
- async function resolveImageSource(
136
- src: string | Uint8Array | ArrayBuffer
137
- ): Promise<Uint8Array> {
138
- if (src instanceof Uint8Array) return src
139
- if (src instanceof ArrayBuffer) return new Uint8Array(src)
140
-
141
- const res = await fetch(src)
142
- if (!res.ok) {
143
- throw new Error(`Failed to load image: ${src}`)
144
- }
145
-
146
- const buffer = await res.arrayBuffer()
147
- return new Uint8Array(buffer)
148
- }
149
-
150
-
151
- function normalizeContent(
152
- content: string | NodeSchema[]
153
- ): NodeSchema[] {
154
- if (typeof content === "string") {
155
- return [
156
- {
157
- type: "text",
158
- content
159
- }
160
- ]
161
- }
162
- return content
163
- }
164
-
165
-
166
- // ==================================================
167
- // Render Engine
168
- // ==================================================
169
-
170
- export async function RenderPDF(
171
- { content }: RenderPDFProps
172
- ): Promise<Uint8Array> {
173
-
174
- const pdf = await PDFDocument.create()
175
-
176
- const fontRegular = await pdf.embedFont(StandardFonts.Courier)
177
- const fontBold = await pdf.embedFont(StandardFonts.CourierBold)
178
-
179
- for (const p of content) {
180
- const size =
181
- typeof p.page.size === "string"
182
- ? PaperSize[p.page.size]
183
- : p.page.size ?? PaperSize.A4
184
-
185
- const margin = p.page.margin ?? 40
186
-
187
- let page: PDFPage = pdf.addPage([size.width, size.height])
188
- const ctx = new LayoutContext(size.width, size.height, margin)
189
-
190
- const draw = async (node: NodeSchema) => {
191
-
192
- // ===================== VIEW =====================
193
- if (node.type === "view") {
194
- const pad = resolvePadding(node.style)
195
- const startY = ctx.y
196
-
197
- ctx.y -= pad.top
198
- ctx.x += pad.left
199
-
200
- for (const c of node.content) await draw(c)
201
-
202
- const endY = ctx.y
203
- const boxHeight = startY - endY
204
-
205
- if (node.style?.backgroundColor) {
206
- page.drawRectangle({
207
- x: ctx.margin,
208
- y: endY,
209
- width: size.width - ctx.margin * 2,
210
- height: boxHeight,
211
- color: hexToRgb(node.style.backgroundColor),
212
- })
213
- }
214
-
215
- if (node.style?.borderWidth && node.style?.borderColor) {
216
- page.drawRectangle({
217
- x: ctx.margin,
218
- y: endY,
219
- width: size.width - ctx.margin * 2,
220
- height: boxHeight,
221
- borderColor: hexToRgb(node.style.borderColor),
222
- borderWidth: node.style.borderWidth,
223
- })
224
- }
225
-
226
- ctx.x -= pad.left
227
- ctx.y -= pad.bottom
228
- return
229
- }
230
-
231
- // ===================== TEXT =====================
232
- if (node.type === "text") {
233
- const style = node.style
234
- const fs = style?.fontSize ?? 12
235
- const lh = style?.lineHeight ?? fs + 4
236
-
237
- if (ctx.needBreak(lh)) {
238
- page = pdf.addPage([size.width, size.height])
239
- ctx.reset()
240
- }
241
-
242
- const font =
243
- style?.fontWeight === "bold"
244
- ? fontBold
245
- : fontRegular
246
-
247
- const text = resolveText(node.content, style)
248
- const color = hexToRgb(style?.color)
249
-
250
- let x = ctx.x
251
- if (style?.align === "center") {
252
- const w = font.widthOfTextAtSize(text, fs)
253
- x = (size.width - w) / 2
254
- }
255
- if (style?.align === "right") {
256
- const w = font.widthOfTextAtSize(text, fs)
257
- x = size.width - ctx.margin - w
258
- }
259
-
260
- page.drawText(text, {
261
- x,
262
- y: ctx.y - fs,
263
- size: fs,
264
- font,
265
- color,
266
- opacity: style?.opacity,
267
- })
268
-
269
- if (style?.underline) {
270
- const w = font.widthOfTextAtSize(text, fs)
271
- page.drawLine({
272
- start: { x, y: ctx.y - fs - 2 },
273
- end: { x: x + w, y: ctx.y - fs - 2 },
274
- thickness: 1,
275
- })
276
- }
277
-
278
- ctx.y -= lh + (style?.marginBottom ?? 0)
279
- return
280
- }
281
-
282
- // ===================== IMAGE =====================
283
- if (node.type === "image") {
284
- const bytes = await resolveImageSource(node.src)
285
- const img = await embedImage(pdf, bytes)
286
- const base = img.scale(1)
287
-
288
- let w = node.style?.width ?? base.width
289
- let h = node.style?.height ?? base.height
290
-
291
- if (node.style?.width && !node.style?.height)
292
- h = (base.height / base.width) * w
293
-
294
- if (node.style?.height && !node.style?.width)
295
- w = (base.width / base.height) * h
296
-
297
- if (ctx.needBreak(h)) {
298
- page = pdf.addPage([size.width, size.height])
299
- ctx.reset()
300
- }
301
-
302
- page.drawImage(img, {
303
- x: ctx.x,
304
- y: ctx.y - h,
305
- width: w,
306
- height: h,
307
- })
308
-
309
- ctx.y -= h + (node.style?.marginBottom ?? 0)
310
- return
311
- }
312
-
313
-
314
- // ===================== TABLE =====================
315
- if (node.type === "table") {
316
- for (const r of node.content) await draw(r)
317
- ctx.y -= 8
318
- return
319
- }
320
-
321
- if (node.type === "tr") {
322
- const rowH = node.style?.height || 20;
323
-
324
- if (ctx.needBreak(rowH)) {
325
- page = pdf.addPage([size.width, size.height])
326
- ctx.reset()
327
- }
328
-
329
- const tableWidth = size.width - ctx.margin * 2
330
- const colCount = node.content.length
331
- const colWidth = tableWidth / colCount
332
-
333
- const originalX = ctx.x
334
- let x = ctx.margin
335
-
336
- for (const cell of node.content) {
337
- if (cell.type !== "td" && cell.type !== "th") continue
338
-
339
- const children = normalizeContent(cell.content)
340
- const pad = resolvePadding(cell.style)
341
- const startY = ctx.y
342
-
343
- ctx.x = x + pad.left
344
- ctx.y -= pad.top
345
-
346
- for (const child of children) {
347
- await draw(child)
348
- }
349
-
350
- ctx.y = startY
351
- x += colWidth
352
- }
353
-
354
- ctx.x = originalX
355
- ctx.y -= rowH
356
- return
357
- }
358
-
359
-
360
-
361
-
362
- }
363
-
364
- for (const n of p.page.content) await draw(n)
365
- }
366
-
367
- return await pdf.save()
368
- }
369
-
370
- export function RenderPDFPreview({ schema, className }: { schema: PageSchema[], className?: string }) {
371
- const canvasRef = useRef<HTMLCanvasElement>(null);
372
-
373
- useEffect(() => {
374
- let cancelled = false;
375
-
376
- (async () => {
377
- const bytes = await RenderPDF({ content: schema });
378
- const pdfjs = await import("pdfjs-dist/legacy/build/pdf.mjs");
379
- pdfjs.GlobalWorkerOptions.workerSrc = "/pdf.worker.min.mjs";
380
-
381
- const pdf = await pdfjs.getDocument({ data: bytes }).promise;
382
- if (cancelled) return;
383
-
384
- const page = await pdf.getPage(1);
385
- const dpr = 1;
386
- const viewport = page.getViewport({ scale: 1 });
387
-
388
- const canvas = canvasRef.current!;
389
- const ctx = canvas.getContext("2d")!;
390
- canvas.style.width = `${viewport.width}px`;
391
- canvas.style.height = `${viewport.height}px`
392
- canvas.width = viewport.width;
393
- canvas.height = viewport.height;
394
-
395
- const scaledViewport = page.getViewport({ scale: dpr });
396
-
397
- const renderTask = page.render({
398
- canvas,
399
- canvasContext: ctx,
400
- viewport: scaledViewport,
401
- });
402
-
403
- await renderTask.promise;
404
- })();
405
-
406
- return () => {
407
- cancelled = true;
408
- };
409
- }, [schema]);
410
-
411
- return <>
412
- <div className={className}>
413
- <canvas ref={canvasRef} className="w-full border" />
414
- </div>
415
- </>
416
- }
@@ -1,85 +0,0 @@
1
- /**
2
- * @file Automatically generated by barrelsby.
3
- */
4
-
5
- export * from "./accordion/Accordion.component";
6
- export * from "./breadcrumb/Breadcrumb.component";
7
- export * from "./button/Button.component";
8
- export * from "./button/button.decorate";
9
- export * from "./button/IconButton.component";
10
- export * from "./card/AlertCard.component";
11
- export * from "./card/Card.component";
12
- export * from "./card/DashboardCard.component";
13
- export * from "./card/GalleryCard.component";
14
- export * from "./card/ProductCard.component";
15
- export * from "./card/ProfileCard.component";
16
- export * from "./carousel/Carousel.component";
17
- export * from "./chip/Chip.component";
18
- export * from "./document/DocumentViewer.component";
19
- export * from "./document/ExportExcel.component";
20
- export * from "./document/ImportExcel.component";
21
- export * from "./document/PrintTable.component";
22
- export * from "./document/RenderPDF.component";
23
- export * from "./input/Checkbox.component";
24
- export * from "./input/Input.component";
25
- export * from "./input/InputCheckbox.component";
26
- export * from "./input/InputCurrency.component";
27
- export * from "./input/InputDate.component";
28
- export * from "./input/InputDatetime.component";
29
- export * from "./input/InputDocument.component";
30
- export * from "./input/InputImage.component";
31
- export * from "./input/InputMap.component";
32
- export * from "./input/InputNumber.component";
33
- export * from "./input/InputOtp.component";
34
- export * from "./input/InputPassword.component";
35
- export * from "./input/InputRadio.component";
36
- export * from "./input/InputTime.component";
37
- export * from "./input/InputValues.component";
38
- export * from "./input/Radio.component";
39
- export * from "./input/Select.component";
40
- export * from "./modal/BottomSheet.component";
41
- export * from "./modal/FloatingPage.component";
42
- export * from "./modal/Modal.component";
43
- export * from "./modal/ModalConfirm.component";
44
- export * from "./modal/Toast.component";
45
- export * from "./nav/Bottombar.component";
46
- export * from "./nav/Footer.component";
47
- export * from "./nav/Headbar.component";
48
- export * from "./nav/Navbar.component";
49
- export * from "./nav/Sidebar.component";
50
- export * from "./nav/Tabbar.component";
51
- export * from "./nav/Wizard.component";
52
- export * from "./supervision/FormSupervision.component";
53
- export * from "./supervision/TableSupervision.component";
54
- export * from "./table/ControlBar.component";
55
- export * from "./table/FilterComponent";
56
- export * from "./table/Pagination.component";
57
- export * from "./table/Table.component";
58
- export * from "./typography/TypographyArticle.component";
59
- export * from "./typography/TypographyColumn.component";
60
- export * from "./typography/TypographyContent.component";
61
- export * from "./typography/TypographyTips.component";
62
- export * from "./wrap/Draggable.component";
63
- export * from "./wrap/IDBProvider";
64
- export * from "./wrap/Image.component";
65
- export * from "./wrap/OutsideClick.component";
66
- export * from "./wrap/ScrollContainer.component";
67
- export * from "./wrap/ShortcutProvider";
68
- export * from "./wrap/Swipe.component";
69
-
70
- import { registry } from "@utils";
71
- import { TableComponent } from "./table/Table.component.js";
72
- import { ButtonComponent } from "./button/Button.component.js";
73
- import { IconButtonComponent } from "./button/IconButton.component.js";
74
- import { SelectComponent } from "./input/Select.component.js";
75
- import { ModalComponent } from "./modal/Modal.component.js";
76
- import { FilterComponent } from "./table/FilterComponent.js";
77
- import { useToggleContext } from "../../contexts/index.js";
78
-
79
- registry.register("TableComponent", TableComponent);
80
- registry.register("ButtonComponent", ButtonComponent);
81
- registry.register("IconButtonComponent", IconButtonComponent);
82
- registry.register("SelectComponent", SelectComponent);
83
- registry.register("ModalComponent", ModalComponent);
84
- registry.register("FilterComponent", FilterComponent);
85
- registry.register("useToggleContext", useToggleContext);
@@ -1,109 +0,0 @@
1
- "use client"
2
-
3
- import { ReactNode, useEffect, useState } from "react";
4
- import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
5
- import { faCheck } from "@fortawesome/free-solid-svg-icons";
6
- import { cn, pcn, useInputRandomId } from "@utils";
7
-
8
-
9
-
10
- type CT = "label" | "checked" | "error" | "base";
11
-
12
- export type CheckboxProps = {
13
- name : string;
14
- label ?: string | ReactNode;
15
-
16
- value ?: string;
17
- disabled ?: boolean;
18
- checked ?: boolean;
19
- invalid ?: string;
20
-
21
- onChange ?: () => void;
22
-
23
- /** Use custom class with: "label::", "checked::", "error::". */
24
- className ?: string;
25
- };
26
-
27
-
28
-
29
- export function CheckboxComponent({
30
- name,
31
- label,
32
-
33
- value,
34
- disabled = false,
35
- checked = false,
36
- invalid,
37
-
38
- onChange,
39
-
40
- className = "",
41
- }: CheckboxProps) {
42
-
43
-
44
- // =========================>
45
- // ## Initial
46
- // =========================>
47
- const randomId = useInputRandomId()
48
- const [invalidMessage, setInvalidMessage] = useState("");
49
-
50
-
51
- // =========================>
52
- // ## Invalid handler
53
- // =========================>
54
- useEffect(() => {
55
- setInvalidMessage(invalid || "");
56
- }, [invalid]);
57
-
58
-
59
- return (
60
- <div className={`flex flex-col gap-1`}>
61
- <input
62
- type="checkbox"
63
- className="hidden"
64
- id={randomId}
65
- name={name}
66
- onChange={onChange}
67
- defaultChecked={checked}
68
- value={value}
69
- disabled={disabled}
70
- />
71
-
72
- <label
73
- htmlFor={randomId}
74
- className={cn(
75
- "flex gap-2 items-center cursor-pointer active:scale-x-[102%]",
76
- disabled && "pointer-events-none opacity-60"
77
- )}
78
- >
79
- <div>
80
- <div
81
- className={cn(
82
- `flex justify-center items-center rounded-md border w-6 h-6 transition-colors border-light-foreground text-light-foreground`,
83
- checked && "border-light-primary bg-primary !text-background",
84
- checked && pcn<CT>(className, "checked"),
85
- pcn<CT>(className, "base"),
86
- )}
87
- >
88
- {checked && <FontAwesomeIcon icon={faCheck} className="text-sm" />}
89
- </div>
90
- </div>
91
- <span
92
- className={cn(
93
- "whitespace-nowrap",
94
- checked && "font-semibold",
95
- pcn<CT>(className, "label"),
96
- checked && pcn<CT>(className, "label", "checked"),
97
- disabled && pcn<CT>(className, "label", "disabled"),
98
- )}
99
- >
100
- {label}
101
- </span>
102
- </label>
103
-
104
- {invalidMessage && (
105
- <small className={cn("input-error-message", pcn<CT>(className, "error"))}>{invalidMessage}</small>
106
- )}
107
- </div>
108
- );
109
- }