@bccampus/ui-components 0.1.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.
Files changed (68) hide show
  1. package/README.md +69 -0
  2. package/components.json +22 -0
  3. package/dist/@bccampus-ui-components-0.1.0.tgz +0 -0
  4. package/dist/button.d.ts +16 -0
  5. package/dist/button.js +36 -0
  6. package/dist/caption.d.ts +13 -0
  7. package/dist/caption.js +27 -0
  8. package/dist/card.d.ts +40 -0
  9. package/dist/card.js +130 -0
  10. package/dist/horizontal-list.d.ts +9 -0
  11. package/dist/horizontal-list.js +145 -0
  12. package/dist/icon-generator.d.ts +50 -0
  13. package/dist/icon-generator.js +270 -0
  14. package/dist/index-DcqAdr0d.js +102 -0
  15. package/dist/jsx-runtime-BzflLqGi.js +282 -0
  16. package/dist/masked-image-generator.d.ts +57 -0
  17. package/dist/masked-image-generator.js +29 -0
  18. package/dist/mockServiceWorker.js +348 -0
  19. package/dist/tag.d.ts +16 -0
  20. package/dist/tag.js +32 -0
  21. package/dist/ui-components.d.ts +132 -0
  22. package/dist/ui-components.js +29 -0
  23. package/dist/utils-CRiPKpXj.js +2743 -0
  24. package/dist/utils.d.ts +5 -0
  25. package/dist/utils.js +4 -0
  26. package/eslint.config.js +31 -0
  27. package/index.html +13 -0
  28. package/package.json +85 -0
  29. package/public/mockServiceWorker.js +348 -0
  30. package/src/App.tsx +14 -0
  31. package/src/assets/icons/icon_01.svg +6 -0
  32. package/src/assets/icons/icon_02.svg +6 -0
  33. package/src/assets/icons/icon_03.svg +6 -0
  34. package/src/assets/icons/icon_04.svg +6 -0
  35. package/src/assets/icons/icon_05.svg +4 -0
  36. package/src/assets/icons/icon_06.svg +4 -0
  37. package/src/assets/images/bg_pattern_01.png +0 -0
  38. package/src/assets/images/bg_pattern_02.png +0 -0
  39. package/src/assets/images/bg_pattern_03.png +0 -0
  40. package/src/assets/images/bg_pattern_04.png +0 -0
  41. package/src/assets/images/image_01.jpg +0 -0
  42. package/src/assets/images/image_02.jpg +0 -0
  43. package/src/assets/images/image_03.webp +0 -0
  44. package/src/assets/images/image_04.png +0 -0
  45. package/src/assets/images/image_05.jpg +0 -0
  46. package/src/components/ui/button.tsx +47 -0
  47. package/src/components/ui/card.tsx +147 -0
  48. package/src/components/ui/horizontal-list.tsx +50 -0
  49. package/src/components/ui/icon-generator/generate-tiles.tsx +243 -0
  50. package/src/components/ui/icon-generator/icon-generator.tsx +51 -0
  51. package/src/components/ui/icon-generator/masked-image-generator.tsx +38 -0
  52. package/src/components/ui/icon-generator/types.ts +53 -0
  53. package/src/components/ui/index.ts +7 -0
  54. package/src/components/ui/tag.tsx +39 -0
  55. package/src/components/ui/typography/caption.tsx +32 -0
  56. package/src/lib/utils.ts +6 -0
  57. package/src/main.tsx +12 -0
  58. package/src/styles/all.css +4 -0
  59. package/src/styles/colors.css +106 -0
  60. package/src/styles/fonts.css +9 -0
  61. package/src/styles/index.css +7 -0
  62. package/src/styles/theme.css +126 -0
  63. package/src/styles/typography.css +479 -0
  64. package/src/vite-env.d.ts +1 -0
  65. package/tsconfig.app.json +38 -0
  66. package/tsconfig.json +19 -0
  67. package/tsconfig.node.json +25 -0
  68. package/vite.config.ts +44 -0
@@ -0,0 +1,5 @@
1
+ import { ClassValue } from 'clsx';
2
+
3
+ export declare function cn(...inputs: ClassValue[]): string;
4
+
5
+ export { }
package/dist/utils.js ADDED
@@ -0,0 +1,4 @@
1
+ import { c as r } from "./utils-CRiPKpXj.js";
2
+ export {
3
+ r as cn
4
+ };
@@ -0,0 +1,31 @@
1
+ import js from '@eslint/js'
2
+ import globals from 'globals'
3
+ import reactHooks, { rules } from 'eslint-plugin-react-hooks'
4
+ import reactRefresh from 'eslint-plugin-react-refresh'
5
+ import tseslint from 'typescript-eslint'
6
+ import { defineConfig, globalIgnores } from 'eslint/config'
7
+
8
+ export default defineConfig([
9
+ globalIgnores(['dist']),
10
+ {
11
+ files: ['**/*.{ts,tsx}'],
12
+ extends: [
13
+ js.configs.recommended,
14
+ tseslint.configs.recommended,
15
+ reactHooks.configs['recommended-latest'],
16
+ reactRefresh.configs.vite,
17
+ ],
18
+ languageOptions: {
19
+ ecmaVersion: 2020,
20
+ globals: globals.browser,
21
+ },
22
+ },
23
+ // shadcn components
24
+ {
25
+ files: ['src/components/ui/**/*.{ts,tsx}'],
26
+ rules: {
27
+ 'react-refresh/only-export-components': 'off',
28
+ },
29
+ },
30
+
31
+ ])
package/index.html ADDED
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Vite + React + TS</title>
8
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script type="module" src="/src/main.tsx"></script>
12
+ </body>
13
+ </html>
package/package.json ADDED
@@ -0,0 +1,85 @@
1
+ {
2
+ "name": "@bccampus/ui-components",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "packageManager": "yarn@4.10.2",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/ui-components.d.ts",
9
+ "import": "./dist/ui-components.js"
10
+ },
11
+ "./button": {
12
+ "types": "./dist/button.d.ts",
13
+ "import": "./dist/button.js"
14
+ },
15
+ "./caption": {
16
+ "types": "./dist/caption.d.ts",
17
+ "import": "./dist/caption.js"
18
+ },
19
+ "./card": {
20
+ "types": "./dist/card.d.ts",
21
+ "import": "./dist/card.js"
22
+ },
23
+ "./tag": {
24
+ "types": "./dist/tag.d.ts",
25
+ "import": "./dist/tag.js"
26
+ },
27
+ "./horizontal-list": {
28
+ "types": "./dist/horizontal-list.d.ts",
29
+ "import": "./dist/horizontal-list.js"
30
+ },
31
+ "./icon-generator": {
32
+ "types": "./dist/icon-generator.d.ts",
33
+ "import": "./dist/icon-generator.js"
34
+ },
35
+ "./masked-image-generator": {
36
+ "types": "./dist/masked-image-generator.d.ts",
37
+ "import": "./dist/masked-image-generator.js"
38
+ },
39
+ "./utils": {
40
+ "types": "./dist/utils.d.ts",
41
+ "import": "./dist/utils.js"
42
+ },
43
+ "./all.css": "./src/styles/all.css",
44
+ "./colors.css": "./src/styles/colors.css",
45
+ "./fonts.css": "./src/styles/fonts.css",
46
+ "./theme.css": "./src/styles/theme.css",
47
+ "./typography.css": "./src/styles/typography.css"
48
+ },
49
+ "scripts": {
50
+ "dev": "vite",
51
+ "build": "tsc -b && vite build",
52
+ "lint": "eslint .",
53
+ "preview": "vite preview"
54
+ },
55
+ "dependencies": {
56
+ "@bcgov/bc-sans": "^2.1.0",
57
+ "@fontsource-variable/inter-tight": "^5.2.7",
58
+ "@ladle/react": "^5.0.3",
59
+ "@radix-ui/react-slot": "^1.2.3",
60
+ "class-variance-authority": "^0.7.1",
61
+ "clsx": "^2.1.1",
62
+ "lucide-react": "^0.544.0",
63
+ "react": "^19.1.1",
64
+ "react-dom": "^19.1.1",
65
+ "tailwind-merge": "^3.3.1",
66
+ "tailwindcss": "^4.1.13",
67
+ "tw-animate-css": "^1.3.8"
68
+ },
69
+ "devDependencies": {
70
+ "@eslint/js": "^9.35.0",
71
+ "@tailwindcss/vite": "^4.1.13",
72
+ "@types/node": "^24.5.2",
73
+ "@types/react": "^19.1.13",
74
+ "@types/react-dom": "^19.1.9",
75
+ "@vitejs/plugin-react-swc": "^4.0.1",
76
+ "eslint": "^9.35.0",
77
+ "eslint-plugin-react-hooks": "^5.2.0",
78
+ "eslint-plugin-react-refresh": "^0.4.20",
79
+ "globals": "^16.4.0",
80
+ "typescript": "~5.8.3",
81
+ "typescript-eslint": "^8.43.0",
82
+ "vite": "^7.1.6",
83
+ "vite-plugin-dts": "^4.5.4"
84
+ }
85
+ }
@@ -0,0 +1,348 @@
1
+ /* eslint-disable */
2
+ /* tslint:disable */
3
+
4
+ /**
5
+ * Mock Service Worker.
6
+ * @see https://github.com/mswjs/msw
7
+ * - Please do NOT modify this file.
8
+ */
9
+
10
+ const PACKAGE_VERSION = '2.11.2'
11
+ const INTEGRITY_CHECKSUM = '4db4a41e972cec1b64cc569c66952d82'
12
+ const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
13
+ const activeClientIds = new Set()
14
+
15
+ addEventListener('install', function () {
16
+ self.skipWaiting()
17
+ })
18
+
19
+ addEventListener('activate', function (event) {
20
+ event.waitUntil(self.clients.claim())
21
+ })
22
+
23
+ addEventListener('message', async function (event) {
24
+ const clientId = Reflect.get(event.source || {}, 'id')
25
+
26
+ if (!clientId || !self.clients) {
27
+ return
28
+ }
29
+
30
+ const client = await self.clients.get(clientId)
31
+
32
+ if (!client) {
33
+ return
34
+ }
35
+
36
+ const allClients = await self.clients.matchAll({
37
+ type: 'window',
38
+ })
39
+
40
+ switch (event.data) {
41
+ case 'KEEPALIVE_REQUEST': {
42
+ sendToClient(client, {
43
+ type: 'KEEPALIVE_RESPONSE',
44
+ })
45
+ break
46
+ }
47
+
48
+ case 'INTEGRITY_CHECK_REQUEST': {
49
+ sendToClient(client, {
50
+ type: 'INTEGRITY_CHECK_RESPONSE',
51
+ payload: {
52
+ packageVersion: PACKAGE_VERSION,
53
+ checksum: INTEGRITY_CHECKSUM,
54
+ },
55
+ })
56
+ break
57
+ }
58
+
59
+ case 'MOCK_ACTIVATE': {
60
+ activeClientIds.add(clientId)
61
+
62
+ sendToClient(client, {
63
+ type: 'MOCKING_ENABLED',
64
+ payload: {
65
+ client: {
66
+ id: client.id,
67
+ frameType: client.frameType,
68
+ },
69
+ },
70
+ })
71
+ break
72
+ }
73
+
74
+ case 'CLIENT_CLOSED': {
75
+ activeClientIds.delete(clientId)
76
+
77
+ const remainingClients = allClients.filter((client) => {
78
+ return client.id !== clientId
79
+ })
80
+
81
+ // Unregister itself when there are no more clients
82
+ if (remainingClients.length === 0) {
83
+ self.registration.unregister()
84
+ }
85
+
86
+ break
87
+ }
88
+ }
89
+ })
90
+
91
+ addEventListener('fetch', function (event) {
92
+ const requestInterceptedAt = Date.now()
93
+
94
+ // Bypass navigation requests.
95
+ if (event.request.mode === 'navigate') {
96
+ return
97
+ }
98
+
99
+ // Opening the DevTools triggers the "only-if-cached" request
100
+ // that cannot be handled by the worker. Bypass such requests.
101
+ if (
102
+ event.request.cache === 'only-if-cached' &&
103
+ event.request.mode !== 'same-origin'
104
+ ) {
105
+ return
106
+ }
107
+
108
+ // Bypass all requests when there are no active clients.
109
+ // Prevents the self-unregistered worked from handling requests
110
+ // after it's been terminated (still remains active until the next reload).
111
+ if (activeClientIds.size === 0) {
112
+ return
113
+ }
114
+
115
+ const requestId = crypto.randomUUID()
116
+ event.respondWith(handleRequest(event, requestId, requestInterceptedAt))
117
+ })
118
+
119
+ /**
120
+ * @param {FetchEvent} event
121
+ * @param {string} requestId
122
+ * @param {number} requestInterceptedAt
123
+ */
124
+ async function handleRequest(event, requestId, requestInterceptedAt) {
125
+ const client = await resolveMainClient(event)
126
+ const requestCloneForEvents = event.request.clone()
127
+ const response = await getResponse(
128
+ event,
129
+ client,
130
+ requestId,
131
+ requestInterceptedAt,
132
+ )
133
+
134
+ // Send back the response clone for the "response:*" life-cycle events.
135
+ // Ensure MSW is active and ready to handle the message, otherwise
136
+ // this message will pend indefinitely.
137
+ if (client && activeClientIds.has(client.id)) {
138
+ const serializedRequest = await serializeRequest(requestCloneForEvents)
139
+
140
+ // Clone the response so both the client and the library could consume it.
141
+ const responseClone = response.clone()
142
+
143
+ sendToClient(
144
+ client,
145
+ {
146
+ type: 'RESPONSE',
147
+ payload: {
148
+ isMockedResponse: IS_MOCKED_RESPONSE in response,
149
+ request: {
150
+ id: requestId,
151
+ ...serializedRequest,
152
+ },
153
+ response: {
154
+ type: responseClone.type,
155
+ status: responseClone.status,
156
+ statusText: responseClone.statusText,
157
+ headers: Object.fromEntries(responseClone.headers.entries()),
158
+ body: responseClone.body,
159
+ },
160
+ },
161
+ },
162
+ responseClone.body ? [serializedRequest.body, responseClone.body] : [],
163
+ )
164
+ }
165
+
166
+ return response
167
+ }
168
+
169
+ /**
170
+ * Resolve the main client for the given event.
171
+ * Client that issues a request doesn't necessarily equal the client
172
+ * that registered the worker. It's with the latter the worker should
173
+ * communicate with during the response resolving phase.
174
+ * @param {FetchEvent} event
175
+ * @returns {Promise<Client | undefined>}
176
+ */
177
+ async function resolveMainClient(event) {
178
+ const client = await self.clients.get(event.clientId)
179
+
180
+ if (activeClientIds.has(event.clientId)) {
181
+ return client
182
+ }
183
+
184
+ if (client?.frameType === 'top-level') {
185
+ return client
186
+ }
187
+
188
+ const allClients = await self.clients.matchAll({
189
+ type: 'window',
190
+ })
191
+
192
+ return allClients
193
+ .filter((client) => {
194
+ // Get only those clients that are currently visible.
195
+ return client.visibilityState === 'visible'
196
+ })
197
+ .find((client) => {
198
+ // Find the client ID that's recorded in the
199
+ // set of clients that have registered the worker.
200
+ return activeClientIds.has(client.id)
201
+ })
202
+ }
203
+
204
+ /**
205
+ * @param {FetchEvent} event
206
+ * @param {Client | undefined} client
207
+ * @param {string} requestId
208
+ * @returns {Promise<Response>}
209
+ */
210
+ async function getResponse(event, client, requestId, requestInterceptedAt) {
211
+ // Clone the request because it might've been already used
212
+ // (i.e. its body has been read and sent to the client).
213
+ const requestClone = event.request.clone()
214
+
215
+ function passthrough() {
216
+ // Cast the request headers to a new Headers instance
217
+ // so the headers can be manipulated with.
218
+ const headers = new Headers(requestClone.headers)
219
+
220
+ // Remove the "accept" header value that marked this request as passthrough.
221
+ // This prevents request alteration and also keeps it compliant with the
222
+ // user-defined CORS policies.
223
+ const acceptHeader = headers.get('accept')
224
+ if (acceptHeader) {
225
+ const values = acceptHeader.split(',').map((value) => value.trim())
226
+ const filteredValues = values.filter(
227
+ (value) => value !== 'msw/passthrough',
228
+ )
229
+
230
+ if (filteredValues.length > 0) {
231
+ headers.set('accept', filteredValues.join(', '))
232
+ } else {
233
+ headers.delete('accept')
234
+ }
235
+ }
236
+
237
+ return fetch(requestClone, { headers })
238
+ }
239
+
240
+ // Bypass mocking when the client is not active.
241
+ if (!client) {
242
+ return passthrough()
243
+ }
244
+
245
+ // Bypass initial page load requests (i.e. static assets).
246
+ // The absence of the immediate/parent client in the map of the active clients
247
+ // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet
248
+ // and is not ready to handle requests.
249
+ if (!activeClientIds.has(client.id)) {
250
+ return passthrough()
251
+ }
252
+
253
+ // Notify the client that a request has been intercepted.
254
+ const serializedRequest = await serializeRequest(event.request)
255
+ const clientMessage = await sendToClient(
256
+ client,
257
+ {
258
+ type: 'REQUEST',
259
+ payload: {
260
+ id: requestId,
261
+ interceptedAt: requestInterceptedAt,
262
+ ...serializedRequest,
263
+ },
264
+ },
265
+ [serializedRequest.body],
266
+ )
267
+
268
+ switch (clientMessage.type) {
269
+ case 'MOCK_RESPONSE': {
270
+ return respondWithMock(clientMessage.data)
271
+ }
272
+
273
+ case 'PASSTHROUGH': {
274
+ return passthrough()
275
+ }
276
+ }
277
+
278
+ return passthrough()
279
+ }
280
+
281
+ /**
282
+ * @param {Client} client
283
+ * @param {any} message
284
+ * @param {Array<Transferable>} transferrables
285
+ * @returns {Promise<any>}
286
+ */
287
+ function sendToClient(client, message, transferrables = []) {
288
+ return new Promise((resolve, reject) => {
289
+ const channel = new MessageChannel()
290
+
291
+ channel.port1.onmessage = (event) => {
292
+ if (event.data && event.data.error) {
293
+ return reject(event.data.error)
294
+ }
295
+
296
+ resolve(event.data)
297
+ }
298
+
299
+ client.postMessage(message, [
300
+ channel.port2,
301
+ ...transferrables.filter(Boolean),
302
+ ])
303
+ })
304
+ }
305
+
306
+ /**
307
+ * @param {Response} response
308
+ * @returns {Response}
309
+ */
310
+ function respondWithMock(response) {
311
+ // Setting response status code to 0 is a no-op.
312
+ // However, when responding with a "Response.error()", the produced Response
313
+ // instance will have status code set to 0. Since it's not possible to create
314
+ // a Response instance with status code 0, handle that use-case separately.
315
+ if (response.status === 0) {
316
+ return Response.error()
317
+ }
318
+
319
+ const mockedResponse = new Response(response.body, response)
320
+
321
+ Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, {
322
+ value: true,
323
+ enumerable: true,
324
+ })
325
+
326
+ return mockedResponse
327
+ }
328
+
329
+ /**
330
+ * @param {Request} request
331
+ */
332
+ async function serializeRequest(request) {
333
+ return {
334
+ url: request.url,
335
+ mode: request.mode,
336
+ method: request.method,
337
+ headers: Object.fromEntries(request.headers.entries()),
338
+ cache: request.cache,
339
+ credentials: request.credentials,
340
+ destination: request.destination,
341
+ integrity: request.integrity,
342
+ redirect: request.redirect,
343
+ referrer: request.referrer,
344
+ referrerPolicy: request.referrerPolicy,
345
+ body: await request.arrayBuffer(),
346
+ keepalive: request.keepalive,
347
+ }
348
+ }
package/src/App.tsx ADDED
@@ -0,0 +1,14 @@
1
+ import { Button } from "@/components/ui/button";
2
+
3
+ function App() {
4
+ return (
5
+ <div className="flex min-h-svh flex-col items-center justify-center">
6
+ <h1 className="font-inter-tight scroll-m-20 text-center text-4xl font-extrabold tracking-tight text-balance">
7
+ Taxing Laughter: The Joke Tax Chronicles
8
+ </h1>
9
+ <Button>Click Here</Button>
10
+ </div>
11
+ );
12
+ }
13
+
14
+ export default App;
@@ -0,0 +1,6 @@
1
+ <svg width="298" height="298" viewBox="0 0 298 298" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M298 0.00782553L298 149.008C215.71 149.008 149 82.2982 149 0.00780599L298 0.00782553Z" fill="currentColor" />
3
+ <path d="M1.3026e-05 0.0078125L149 0.00782553C149 82.2983 82.2904 149.008 0 149.008L1.3026e-05 0.0078125Z" class="fill-current" />
4
+ <path d="M149 149.008L298 149.008C298 231.298 231.29 298.008 149 298.008L149 149.008Z" class="fill-current" />
5
+ <path d="M149 149.008L149 298.008C66.7096 298.008 -1.07911e-05 231.298 0 149.008L149 149.008Z" class="fill-current" />
6
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg width="298" height="298" viewBox="0 0 298 298" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M1.3026e-05 298.008L149 298.008C149 215.717 82.2904 149.008 1.3026e-05 149.008L1.3026e-05 298.008Z" fill="#2E5776"/>
3
+ <path d="M1.3026e-05 0.0078125L149 0.00785158C149 82.2983 82.2904 149.008 -2.6052e-05 149.008L1.3026e-05 0.0078125Z" fill="#2E5776"/>
4
+ <path d="M298 149.008L149 149.008C149 231.298 215.71 298.008 298 298.008L298 149.008Z" fill="#2E5776"/>
5
+ <path d="M298 149.008L149 149.008C149 66.7173 215.71 0.00778372 298 0.0078125L298 149.008Z" fill="#2E5776"/>
6
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg width="299" height="299" viewBox="0 0 299 299" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M0.937513 0.0625L149.938 0.062513C149.938 82.3529 83.2279 149.063 0.9375 149.062L0.937513 0.0625Z" fill="#2E5776"/>
3
+ <path d="M0.937513 149.062L149.938 149.063C149.938 231.353 83.2279 298.063 0.9375 298.062L0.937513 149.062Z" fill="#2E5776"/>
4
+ <path d="M149.938 0.0625L298.938 0.062513C298.938 82.3529 232.228 149.063 149.938 149.062L149.938 0.0625Z" fill="#2E5776"/>
5
+ <path d="M149.938 149.062L298.938 149.063C298.938 231.353 232.228 298.063 149.938 298.062L149.938 149.062Z" fill="#2E5776"/>
6
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg width="298" height="299" viewBox="0 0 298 299" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M1.3026e-05 0.0703125L149 0.0703255C149 82.3608 82.2904 149.07 0 149.07L1.3026e-05 0.0703125Z" fill="#2E5776"/>
3
+ <path d="M0 298.07L6.513e-06 149.07C82.2904 149.07 149 215.78 149 298.07L0 298.07Z" fill="#2E5776"/>
4
+ <path d="M298 0.0703255L298 149.07C215.71 149.07 149 82.3607 149 0.070306L298 0.0703255Z" fill="#2E5776"/>
5
+ <path d="M298 298.07L149 298.07C149 215.78 215.71 149.07 298 149.07L298 298.07Z" fill="#2E5776"/>
6
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="298" height="298" viewBox="0 0 298 298" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M149 149C231.29 149 298 215.71 298 298H0C0 215.71 66.7096 149 149 149Z" fill="#2E5776"/>
3
+ <path d="M149 149C66.7096 149 5.83194e-06 82.2904 1.3026e-05 -2.6052e-05L298 0C298 82.2904 231.29 149 149 149Z" fill="#2E5776"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="298" height="298" viewBox="0 0 298 298" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M149 149C149 66.7096 215.71 -2.91597e-06 298 -6.513e-06L298 298C215.71 298 149 231.29 149 149Z" fill="#2E5776"/>
3
+ <path d="M149 149C149 231.29 82.2904 298 -1.3026e-05 298L0 -6.513e-06C82.2904 -2.91597e-06 149 66.7096 149 149Z" fill="#2E5776"/>
4
+ </svg>
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,47 @@
1
+ import { Slot } from "@radix-ui/react-slot";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+
4
+ import { cn } from "@/lib/utils";
5
+
6
+ const buttonVariants = cva(
7
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-sm text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default:
12
+ "bg-primary text-primary-foreground hover:bg-secondary dark:bg-complement-1-50 dark:text-brand-1 dark:hover:bg-complement-1-100",
13
+ secondary:
14
+ "bg-secondary text-secondary-foreground hover:bg-background hover:text-primary dark:bg-complement-1-500 dark:text-foreground dark:hover:bg-complement-1-600",
15
+ outline:
16
+ "border border-primary bg-transparent hover:border-secondary hover:bg-secondary/10 dark:border-input dark:hover:bg-input/50",
17
+ ghost: "text-secondary hover:bg-primary/10 dark:text-foreground dark:hover:bg-complement-1-800",
18
+ link: "text-primary underline-offset-4 hover:underline",
19
+ destructive:
20
+ "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
21
+ },
22
+ size: {
23
+ default: "h-9 px-6 py-2 has-[>svg]:px-3",
24
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
25
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
26
+ icon: "size-9",
27
+ },
28
+ },
29
+ defaultVariants: {
30
+ variant: "default",
31
+ size: "default",
32
+ },
33
+ }
34
+ );
35
+
36
+ type ButtonProps = React.ComponentProps<"button"> &
37
+ VariantProps<typeof buttonVariants> & {
38
+ asChild?: boolean;
39
+ };
40
+
41
+ function Button({ className, variant, size, asChild = false, ...props }: ButtonProps) {
42
+ const Comp = asChild ? Slot : "button";
43
+
44
+ return <Comp data-slot="button" className={cn(buttonVariants({ variant, size }), className)} {...props} />;
45
+ }
46
+
47
+ export { Button, buttonVariants };