lark-docs-variables 1.0.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 (49) hide show
  1. package/.vscode/launch.json +18 -0
  2. package/.vscode/settings.json +42 -0
  3. package/README.md +1 -0
  4. package/app.json +19 -0
  5. package/components.json +38 -0
  6. package/eslint.config.js +123 -0
  7. package/package.json +55 -0
  8. package/src/components/Box.tsx +10 -0
  9. package/src/components/Icon.module.css +3 -0
  10. package/src/components/Icon.tsx +26 -0
  11. package/src/components/ValueToggle.module.css +4 -0
  12. package/src/components/ValueToggle.tsx +25 -0
  13. package/src/components/base/Button.tsx +46 -0
  14. package/src/components/base/Card.tsx +74 -0
  15. package/src/components/base/Combobox.tsx +217 -0
  16. package/src/components/base/Input.tsx +17 -0
  17. package/src/components/base/InputGroup.tsx +123 -0
  18. package/src/components/base/Textarea.tsx +15 -0
  19. package/src/components/base/Toggle.tsx +24 -0
  20. package/src/entries/Panel.module.css +33 -0
  21. package/src/entries/Panel.tsx +67 -0
  22. package/src/entries/Settings.css +3 -0
  23. package/src/entries/Settings.module.css +4 -0
  24. package/src/entries/Settings.tsx +14 -0
  25. package/src/globals.d.ts +1 -0
  26. package/src/hooks/useBlockHover.ts +20 -0
  27. package/src/hooks/useDebounce.ts +16 -0
  28. package/src/hooks/useDocument.ts +8 -0
  29. package/src/hooks/useIsMounted.ts +15 -0
  30. package/src/hooks/useRecord.ts +33 -0
  31. package/src/hooks/useResizeObserver.ts +90 -0
  32. package/src/hooks/useSelection.ts +16 -0
  33. package/src/hooks/useTimeoutFn.ts +40 -0
  34. package/src/index.css +125 -0
  35. package/src/lib/utils.ts +6 -0
  36. package/src/panel.html +11 -0
  37. package/src/panel.tsx +14 -0
  38. package/src/providers/BlockProvider.context.ts +10 -0
  39. package/src/providers/BlockProvider.tsx +30 -0
  40. package/src/public/icon.png +0 -0
  41. package/src/settings.html +11 -0
  42. package/src/settings.tsx +14 -0
  43. package/src/util/app.ts +3 -0
  44. package/src/util/box.ts +27 -0
  45. package/tsconfig.app.json +35 -0
  46. package/tsconfig.json +13 -0
  47. package/tsconfig.node.json +26 -0
  48. package/vite/plugin.ts +131 -0
  49. package/vite.config.ts +55 -0
@@ -0,0 +1,18 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [{
4
+ "type": "node",
5
+ "request": "launch",
6
+ "name": "vite:build",
7
+ "skipFiles": ["<node_internals>/**", "build/**"],
8
+ "program": "${workspaceFolder}/node_modules/vite/bin/vite.js",
9
+ "args": ["build"]
10
+ }, {
11
+ "type": "node",
12
+ "request": "launch",
13
+ "name": "vite:dev",
14
+ "skipFiles": ["<node_internals>/**", "build/**"],
15
+ "program": "${workspaceFolder}/node_modules/vite/bin/vite.js",
16
+ "args": ["dev"]
17
+ }]
18
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "[jsonc]": {
3
+ "editor.formatOnSave": false
4
+ },
5
+ "[css]": {
6
+ "editor.formatOnSave": false
7
+ },
8
+ "[tailwindcss]": {
9
+ "editor.formatOnSave": false
10
+ },
11
+ "[html]": {
12
+ "editor.formatOnSave": false
13
+ },
14
+ "editor.codeActionsOnSave": {
15
+ "source.fixAll.eslint": "explicit",
16
+ "source.organizeImports": "explicit"
17
+ },
18
+ "typescript.preferences.importModuleSpecifier": "relative",
19
+ "editor.formatOnSave": true,
20
+ "editor.rulers": [80],
21
+ "editor.tabCompletion": "on",
22
+ "editor.tabSize": 2,
23
+ "editor.trimAutoWhitespace": true,
24
+ "eslint.nodePath": "./node_modules",
25
+ "eslint.run": "onType",
26
+ "files.exclude": {
27
+ "**/.DS_Store": true,
28
+ "**/.git": true,
29
+ "**/dist": false,
30
+ "**/node_modules": true,
31
+ "**/tsconfig.tsbuildinfo": true
32
+ },
33
+ "files.insertFinalNewline": true,
34
+ "files.trimTrailingWhitespace": true,
35
+ "javascript.preferences.quoteStyle": "single",
36
+ "json.format.enable": false,
37
+ "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true,
38
+ "typescript.format.semicolons": "remove",
39
+ "typescript.preferences.quoteStyle": "single",
40
+ "typescript.tsdk": "node_modules/typescript/lib",
41
+ "typescript.updateImportsOnFileMove.enabled": "never"
42
+ }
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # Atomic BI Lark Addons
package/app.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "manifestVersion": 1,
3
+ "appID": "cli_a72c3455d2b8d02f",
4
+ "appType": "docs-addon",
5
+ "blockTypeID": "blk_67a6884873800020d68db80f",
6
+ "projectName": "addons",
7
+ "url": "https://atomicbi.sg.larksuite.com/wiki/AGlQwmkbAiadxgkbzYel4Zufgoe",
8
+ "contributes": {
9
+ "addPanel": { "initialHeight": 36, "view": "panel.html" },
10
+ "modal": { "initialHeight": 420, "view": "settings.html" }
11
+ },
12
+ "meta": {
13
+ "appName": { "zh-CN": "Atomic BI", "en-US": "Atomic BI", "ja-JP": "Atomic BI" },
14
+ "name": { "zh-CN": "Variable", "en-US": "Variable", "ja-JP": "Variable" },
15
+ "icon": "https://pan16.larksuitecdn.com/static-resource/v1/v3_00ja_a234a524-aef8-49fc-b26d-abd364307fhu",
16
+ "filledIcon": "https://pan16.larksuitecdn.com/static-resource/v1/v3_00ja_a234a524-aef8-49fc-b26d-abd364307fhu",
17
+ "outlinedIcon": "https://pan16.larksuitecdn.com/static-resource/v1/v3_00ja_a234a524-aef8-49fc-b26d-abd364307fhu"
18
+ }
19
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "base-vega",
4
+ "rsc": false,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "",
8
+ "css": "src/index.css",
9
+ "baseColor": "neutral",
10
+ "cssVariables": true,
11
+ "prefix": ""
12
+ },
13
+ "iconLibrary": "lucide",
14
+ "fileCase": "pascalCase",
15
+ "transform": {
16
+ "enforceNamedImports": true,
17
+ "enforceDirectExports": true,
18
+ "enforceFunctionComponent": true,
19
+ "enforceFormat": true,
20
+ "enforceEslint": true,
21
+ "enforcePrettier": true,
22
+ "enforceLineSeparation": true,
23
+ "eslint": {
24
+ "@typescript-eslint/consistent-type-imports": ["error", {
25
+ "disallowTypeAnnotations": true,
26
+ "prefer": "no-type-imports"
27
+ }]
28
+ }
29
+ },
30
+ "aliases": {
31
+ "components": "@/components",
32
+ "utils": "@/lib/utils",
33
+ "ui": "@/components/base",
34
+ "lib": "@/lib",
35
+ "hooks": "@/hooks"
36
+ },
37
+ "registries": {}
38
+ }
@@ -0,0 +1,123 @@
1
+ import eslint from '@eslint/js'
2
+ import stylistic from '@stylistic/eslint-plugin'
3
+ import jsxA11y from 'eslint-plugin-jsx-a11y'
4
+ import react from 'eslint-plugin-react'
5
+ import reactHooks from 'eslint-plugin-react-hooks'
6
+ import reactRefresh from 'eslint-plugin-react-refresh'
7
+ import { defineConfig, globalIgnores } from 'eslint/config'
8
+ import globals from 'globals'
9
+ import tseslint from 'typescript-eslint'
10
+
11
+ export default defineConfig([
12
+ globalIgnores(['dist']),
13
+ {
14
+ files: ['src/**/*.{ts,tsx}', 'vite/**/*.{ts,tsx}'],
15
+ extends: [
16
+ eslint.configs.recommended,
17
+ tseslint.configs.recommendedTypeChecked,
18
+ tseslint.configs.stylisticTypeChecked,
19
+ reactHooks.configs.flat.recommended,
20
+ reactRefresh.configs.vite,
21
+ ],
22
+ languageOptions: {
23
+ ecmaVersion: 2020,
24
+ parserOptions: {
25
+ projectService: true,
26
+ ecmaFeatures: { jsx: true }
27
+ },
28
+ globals: globals.browser,
29
+ },
30
+ plugins: {
31
+ '@stylistic': stylistic,
32
+ 'jsx-a11y': jsxA11y,
33
+ 'react': react,
34
+ 'react-hooks': reactHooks
35
+ },
36
+ rules: {
37
+ '@stylistic/space-in-parens': ['error'],
38
+ '@stylistic/comma-spacing': ['error'],
39
+ '@stylistic/no-multi-spaces': ['error'],
40
+ '@stylistic/no-trailing-spaces': ['error'],
41
+ '@stylistic/no-whitespace-before-property': ['error'],
42
+ '@stylistic/array-bracket-newline': ['error', 'consistent'],
43
+ '@stylistic/array-bracket-spacing': ['error'],
44
+ '@stylistic/arrow-spacing': ['error'],
45
+ '@stylistic/arrow-parens': ['error', 'always'],
46
+ '@stylistic/block-spacing': ['error', 'always'],
47
+ '@stylistic/brace-style': ['error', '1tbs', { 'allowSingleLine': true }],
48
+ '@stylistic/comma-dangle': ['error', 'never'],
49
+ '@stylistic/key-spacing': ['error'],
50
+ '@stylistic/keyword-spacing': ['error'],
51
+ '@stylistic/member-delimiter-style': ['error', { 'multiline': { 'delimiter': 'none' } }],
52
+ '@stylistic/no-extra-semi': ['error'],
53
+ '@stylistic/indent': ['error', 2],
54
+ '@stylistic/no-multiple-empty-lines': ['error', { 'max': 1, 'maxEOF': 0, 'maxBOF': 0 }],
55
+ '@stylistic/object-curly-spacing': ['error', 'always'],
56
+ '@stylistic/quotes': ['error', 'single'],
57
+ '@stylistic/semi': ['error', 'never'],
58
+ '@stylistic/space-before-blocks': ['error', 'always'],
59
+ '@stylistic/space-before-function-paren': ['error', { 'anonymous': 'always', 'named': 'never', 'asyncArrow': 'always' }],
60
+ '@typescript-eslint/adjacent-overload-signatures': 'error',
61
+ '@typescript-eslint/array-type': 'off',
62
+ '@typescript-eslint/await-thenable': 'off',
63
+ '@typescript-eslint/unbound-method': 'off',
64
+ '@typescript-eslint/no-unsafe-enum-comparison': 'off',
65
+ '@typescript-eslint/no-unsafe-function-type': 'off',
66
+ '@typescript-eslint/ban-types': 'off',
67
+ '@typescript-eslint/consistent-type-assertions': 'off',
68
+ '@typescript-eslint/explicit-function-return-type': 'off',
69
+ '@typescript-eslint/explicit-member-accessibility': 'off',
70
+ '@typescript-eslint/no-angle-bracket-type-assertion': 'off',
71
+ '@typescript-eslint/no-empty-function': 'off',
72
+ '@typescript-eslint/no-empty-interface': 'off',
73
+ '@typescript-eslint/no-extra-non-null-assertion': 'error',
74
+ '@typescript-eslint/no-floating-promises': 'off',
75
+ '@typescript-eslint/no-misused-new': 'error',
76
+ '@typescript-eslint/no-misused-promises': 'off',
77
+ '@typescript-eslint/no-namespace': 'off',
78
+ '@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
79
+ '@typescript-eslint/no-non-null-assertion': 'off',
80
+ '@typescript-eslint/no-object-literal-type-assertion': 'off',
81
+ '@typescript-eslint/no-parameter-properties': 'off',
82
+ '@typescript-eslint/no-shadow': 'error',
83
+ '@typescript-eslint/no-triple-slash-reference': 'off',
84
+ '@typescript-eslint/no-unused-vars': ['error', {
85
+ 'args': 'all',
86
+ 'argsIgnorePattern': '^_',
87
+ 'caughtErrors': 'all',
88
+ 'caughtErrorsIgnorePattern': '^_',
89
+ 'destructuredArrayIgnorePattern': '^_',
90
+ 'varsIgnorePattern': '^_',
91
+ 'ignoreRestSiblings': true
92
+ }],
93
+ '@typescript-eslint/no-use-before-define': 'off',
94
+ '@typescript-eslint/no-var-requires': 'off',
95
+ '@typescript-eslint/prefer-for-of': 'error',
96
+ '@typescript-eslint/prefer-interface': 'off',
97
+ '@typescript-eslint/prefer-nullish-coalescing': 'off',
98
+ '@typescript-eslint/prefer-optional-chain': 'error',
99
+ '@typescript-eslint/return-await': 'off',
100
+ '@typescript-eslint/unified-signatures': 'error',
101
+ '@typescript-eslint/no-unsafe-return': 'off',
102
+ '@typescript-eslint/no-redundant-type-constituents': 'off',
103
+ '@typescript-eslint/no-unsafe-member-access': 'off',
104
+ '@typescript-eslint/no-unsafe-call': 'off',
105
+ '@typescript-eslint/no-unsafe-argument': 'off',
106
+ '@typescript-eslint/no-unsafe-assignment': 'off',
107
+ '@typescript-eslint/dot-notation': 'off',
108
+ '@typescript-eslint/prefer-regexp-exec': 'off',
109
+ '@typescript-eslint/require-await': 'off',
110
+ '@typescript-eslint/only-throw-error': ['error', {
111
+ 'allow': [
112
+ { from: 'lib', name: 'Response' },
113
+ { from: 'package', package: 'react-router', name: 'DataWithResponseInit' }
114
+ ]
115
+ }],
116
+ 'jsx-a11y/no-autofocus': ['error', { 'ignoreNonDOM': true }],
117
+ 'jsx-a11y/aria-role': ['error', { 'ignoreNonDOM': true }],
118
+ '@typescript-eslint/no-base-to-string': 'off',
119
+ '@typescript-eslint/restrict-template-expressions': 'off',
120
+ 'react-hooks/exhaustive-deps': 'off'
121
+ }
122
+ }
123
+ ])
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "lark-docs-variables",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "dependencies": {
6
+ "@base-ui/react": "^1.1.0",
7
+ "@lark-opdev/block-docs-addon-api": "^0.0.10",
8
+ "@lark-opdev/cli": "3.3.2",
9
+ "@tailwindcss/vite": "^4.1.18",
10
+ "class-variance-authority": "^0.7.1",
11
+ "clsx": "^2.1.1",
12
+ "lucide-react": "^0.563.0",
13
+ "react": "^19.2.0",
14
+ "react-dom": "^19.2.0",
15
+ "tailwind-merge": "^3.4.0",
16
+ "tailwindcss": "^4.1.18"
17
+ },
18
+ "devDependencies": {
19
+ "@eslint/js": "^9.39.1",
20
+ "@stylistic/eslint-plugin": "^2.11.0",
21
+ "@types/lodash.merge": "^4.6.9",
22
+ "@types/node": "^24.10.1",
23
+ "@types/react": "^19.2.5",
24
+ "@types/react-dom": "^19.2.3",
25
+ "@typescript-eslint/utils": "^8.17.0",
26
+ "@vitejs/plugin-react": "^5.1.1",
27
+ "axios": "^1.13.2",
28
+ "block-docs-addon-vite-utils": "^1.0.1",
29
+ "eslint": "^9.39.1",
30
+ "eslint-plugin-jsx-a11y": "^6.10.2",
31
+ "eslint-plugin-react": "^7.37.2",
32
+ "eslint-plugin-react-hooks": "^7.0.1",
33
+ "eslint-plugin-react-refresh": "^0.4.24",
34
+ "globals": "^16.5.0",
35
+ "lodash.merge": "^4.6.2",
36
+ "open": "^11.0.0",
37
+ "picocolors": "^1.1.1",
38
+ "query-string": "^9.3.1",
39
+ "react-refresh": "^0.14.0",
40
+ "rimraf": "^6.1.2",
41
+ "typescript": "~5.9.3",
42
+ "typescript-eslint": "^8.46.4",
43
+ "vite": "^7.2.4"
44
+ },
45
+ "resolutions": {
46
+ "vite": "7.2.4"
47
+ },
48
+ "scripts": {
49
+ "serve": "vite",
50
+ "build": "tsc -b && vite build",
51
+ "lint": "eslint .",
52
+ "preview": "vite preview",
53
+ "upload": "pnpm build && opdev upload ./dist"
54
+ }
55
+ }
@@ -0,0 +1,10 @@
1
+ import { type ComponentProps, type FunctionComponent } from 'react'
2
+ import { type BoxProps, box } from '../util/box'
3
+
4
+ export const Box: FunctionComponent<BoxProps & ComponentProps<'div'>> = ({ flex, gap, m, p, children, ...props }) => {
5
+ return (
6
+ <div style={box({ flex, gap, m, p })} {...props}>
7
+ {children}
8
+ </div>
9
+ )
10
+ }
@@ -0,0 +1,3 @@
1
+ .icon {
2
+ display: block;
3
+ }
@@ -0,0 +1,26 @@
1
+ import { type FunctionComponent } from 'react'
2
+ import styles from './Icon.module.css'
3
+
4
+ export interface IconProps {
5
+ size?: number
6
+ }
7
+
8
+ export const CaretUpIcon: FunctionComponent<IconProps> = ({ size = 16 }) => {
9
+ return (
10
+ <svg className={styles['icon']} width={size} height={size} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
11
+ <path fillRule="evenodd" clipRule="evenodd" d="M7.00003 15.5C6.59557 15.5 6.23093 15.2564 6.07615 14.8827C5.92137 14.509 6.00692 14.0789 6.29292 13.7929L11.2929 8.79289C11.6834 8.40237 12.3166 8.40237 12.7071 8.79289L17.7071 13.7929C17.9931 14.0789 18.0787 14.509 17.9239 14.8827C17.7691 15.2564 17.4045 15.5 17 15.5H7.00003Z" fill="currentColor" />
12
+ </svg>
13
+ )
14
+ }
15
+
16
+ <svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
17
+
18
+ </svg>
19
+
20
+ export const CaretDownIcon: FunctionComponent<IconProps> = ({ size = 16 }) => {
21
+ return (
22
+ <svg className={styles['icon']} width={size} height={size} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
23
+ <path fillRule="evenodd" clipRule="evenodd" d="M7.00003 8.5C6.59557 8.5 6.23093 8.74364 6.07615 9.11732C5.92137 9.49099 6.00692 9.92111 6.29292 10.2071L11.2929 15.2071C11.6834 15.5976 12.3166 15.5976 12.7071 15.2071L17.7071 10.2071C17.9931 9.92111 18.0787 9.49099 17.9239 9.11732C17.7691 8.74364 17.4045 8.5 17 8.5H7.00003Z" fill="currentColor" />
24
+ </svg>
25
+ )
26
+ }
@@ -0,0 +1,4 @@
1
+ .toggle {
2
+ font-size: 13px;
3
+ font-family: "SourceCodeProMac";
4
+ }
@@ -0,0 +1,25 @@
1
+ import { LucideProps } from 'lucide-react'
2
+ import { ForwardRefExoticComponent, FunctionComponent, RefAttributes } from 'react'
3
+ import { Toggle } from './base/Toggle'
4
+ import styles from './ValueToggle.module.css'
5
+
6
+ export interface ValueToggleProps {
7
+ value: boolean
8
+ onChange: (value: boolean) => void
9
+ label?: string | ((value: boolean) => string)
10
+ icon: ForwardRefExoticComponent<Omit<LucideProps, 'ref'> & RefAttributes<SVGSVGElement>>
11
+ }
12
+
13
+ export const ValueToggle: FunctionComponent<ValueToggleProps> = ({ value, onChange, label, icon: Icon }) => {
14
+ const color = value ? 'var(--foreground)' : 'var(--muted-foreground)'
15
+ return (
16
+ <Toggle className={styles['toggle']} size='sm' variant='default' pressed={value ?? false} onPressedChange={onChange}>
17
+ <Icon size={16} color={value ? 'var(--foreground)' : 'var(--muted-foreground)'} />
18
+ {label && (
19
+ <span style={{ fontWeight: 400, color }}>
20
+ {(typeof label === 'string') ? label : label(value)}
21
+ </span>
22
+ )}
23
+ </Toggle>
24
+ )
25
+ }
@@ -0,0 +1,46 @@
1
+ import { cn } from '@/lib/utils'
2
+ import { Button as ButtonPrimitive } from '@base-ui/react/button'
3
+ import { VariantProps, cva } from 'class-variance-authority'
4
+ import { FunctionComponent } from 'react'
5
+
6
+ const buttonVariants = cva(
7
+ 'focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-md border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] [&_svg:not([class*=\'size-\'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none',
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: 'bg-primary text-primary-foreground hover:bg-primary/80',
12
+ outline:
13
+ 'border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground shadow-xs',
14
+ secondary:
15
+ 'bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground',
16
+ ghost:
17
+ 'hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground',
18
+ destructive:
19
+ 'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30',
20
+ link: 'text-primary underline-offset-4 hover:underline'
21
+ },
22
+ size: {
23
+ 'default':
24
+ 'h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',
25
+ 'xs': 'h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*=\'size-\'])]:size-3',
26
+ 'sm': 'h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5',
27
+ 'lg': 'h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3',
28
+ 'icon': 'size-9',
29
+ 'icon-xs':
30
+ 'size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*=\'size-\'])]:size-3',
31
+ 'icon-sm': 'size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md',
32
+ 'icon-lg': 'size-10'
33
+ }
34
+ },
35
+ defaultVariants: { variant: 'default', size: 'default' }
36
+ }
37
+ )
38
+
39
+ export const Button: FunctionComponent<ButtonPrimitive.Props & VariantProps<typeof buttonVariants>> = ({
40
+ className,
41
+ variant = 'default',
42
+ size = 'default',
43
+ ...props
44
+ }) => {
45
+ return <ButtonPrimitive data-slot='button' className={cn(buttonVariants({ variant, size, className }))} {...props} />
46
+ }
@@ -0,0 +1,74 @@
1
+ import { cn } from '@/lib/utils'
2
+ import { ComponentProps, FunctionComponent } from 'react'
3
+
4
+ export const Card: FunctionComponent<ComponentProps<'div'> & { size?: 'default' | 'sm' }> = ({
5
+ className,
6
+ size = 'default',
7
+ ...props
8
+ }) => {
9
+ return (
10
+ <div
11
+ data-slot='card'
12
+ data-size={size}
13
+ className={cn(
14
+ 'ring-foreground/10 bg-card text-card-foreground gap-6 overflow-hidden rounded-xl py-6 text-sm shadow-xs ring-1 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col',
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ )
20
+ }
21
+
22
+ export const CardHeader: FunctionComponent<ComponentProps<'div'>> = ({ className, ...props }) => {
23
+ return (
24
+ <div
25
+ data-slot='card-header'
26
+ className={cn(
27
+ 'gap-1 rounded-t-xl px-6 group-data-[size=sm]/card:px-4 [.border-b]:pb-6 group-data-[size=sm]/card:[.border-b]:pb-4 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]',
28
+ className
29
+ )}
30
+ {...props}
31
+ />
32
+ )
33
+ }
34
+
35
+ export const CardTitle: FunctionComponent<ComponentProps<'div'>> = ({ className, ...props }) => {
36
+ return (
37
+ <div
38
+ data-slot='card-title'
39
+ className={cn('text-base leading-normal font-medium group-data-[size=sm]/card:text-sm', className)}
40
+ {...props}
41
+ />
42
+ )
43
+ }
44
+
45
+ export const CardDescription: FunctionComponent<ComponentProps<'div'>> = ({ className, ...props }) => {
46
+ return <div data-slot='card-description' className={cn('text-muted-foreground text-sm', className)} {...props} />
47
+ }
48
+
49
+ export const CardAction: FunctionComponent<ComponentProps<'div'>> = ({ className, ...props }) => {
50
+ return (
51
+ <div
52
+ data-slot='card-action'
53
+ className={cn('col-start-2 row-span-2 row-start-1 self-start justify-self-end', className)}
54
+ {...props}
55
+ />
56
+ )
57
+ }
58
+
59
+ export const CardContent: FunctionComponent<ComponentProps<'div'>> = ({ className, ...props }) => {
60
+ return <div data-slot='card-content' className={cn('px-6 group-data-[size=sm]/card:px-4', className)} {...props} />
61
+ }
62
+
63
+ export const CardFooter: FunctionComponent<ComponentProps<'div'>> = ({ className, ...props }) => {
64
+ return (
65
+ <div
66
+ data-slot='card-footer'
67
+ className={cn(
68
+ 'rounded-b-xl px-6 group-data-[size=sm]/card:px-4 [.border-t]:pt-6 group-data-[size=sm]/card:[.border-t]:pt-4 flex items-center',
69
+ className
70
+ )}
71
+ {...props}
72
+ />
73
+ )
74
+ }