@1001-digital/components 0.0.1

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 (52) hide show
  1. package/package.json +45 -0
  2. package/src/base/components/Actions.vue +57 -0
  3. package/src/base/components/Alert.vue +90 -0
  4. package/src/base/components/Button.vue +260 -0
  5. package/src/base/components/Card.vue +78 -0
  6. package/src/base/components/CardLink.vue +56 -0
  7. package/src/base/components/Dialog.vue +274 -0
  8. package/src/base/components/Dropdown.vue +167 -0
  9. package/src/base/components/DropdownCheckboxItem.vue +30 -0
  10. package/src/base/components/DropdownGroup.vue +9 -0
  11. package/src/base/components/DropdownItem.vue +23 -0
  12. package/src/base/components/DropdownLabel.vue +9 -0
  13. package/src/base/components/DropdownRadioGroup.vue +15 -0
  14. package/src/base/components/DropdownRadioItem.vue +29 -0
  15. package/src/base/components/DropdownSeparator.vue +7 -0
  16. package/src/base/components/DropdownSub.vue +58 -0
  17. package/src/base/components/Form.vue +27 -0
  18. package/src/base/components/FormCheckbox.vue +92 -0
  19. package/src/base/components/FormGroup.vue +39 -0
  20. package/src/base/components/FormInputGroup.vue +55 -0
  21. package/src/base/components/FormItem.vue +89 -0
  22. package/src/base/components/FormLabel.vue +39 -0
  23. package/src/base/components/FormRadioGroup.vue +118 -0
  24. package/src/base/components/FormSelect.vue +160 -0
  25. package/src/base/components/FormTextarea.vue +38 -0
  26. package/src/base/components/Icon.vue +29 -0
  27. package/src/base/components/Loading.vue +81 -0
  28. package/src/base/components/Popover.vue +182 -0
  29. package/src/base/components/Tag.vue +56 -0
  30. package/src/base/components/Tags.vue +13 -0
  31. package/src/base/components/Toasts.vue +254 -0
  32. package/src/base/components/Tooltip.vue +100 -0
  33. package/src/base/composables/time.ts +82 -0
  34. package/src/base/composables/toast.ts +40 -0
  35. package/src/base/icons.ts +20 -0
  36. package/src/base/link.ts +4 -0
  37. package/src/base/utils/format-number.ts +29 -0
  38. package/src/base/utils/time.ts +20 -0
  39. package/src/evm/components/EvmAccount.vue +28 -0
  40. package/src/evm/components/EvmConnect.vue +254 -0
  41. package/src/evm/components/EvmConnectorQR.vue +116 -0
  42. package/src/evm/components/EvmMetaMaskQR.vue +15 -0
  43. package/src/evm/components/EvmTransactionFlow.vue +327 -0
  44. package/src/evm/components/EvmWalletConnectQR.vue +13 -0
  45. package/src/evm/composables/base.ts +7 -0
  46. package/src/evm/composables/chainId.ts +41 -0
  47. package/src/evm/config.ts +32 -0
  48. package/src/evm/index.ts +25 -0
  49. package/src/evm/utils/addresses.ts +6 -0
  50. package/src/evm/utils/chains.ts +32 -0
  51. package/src/evm/utils/format-eth.ts +15 -0
  52. package/src/index.ts +68 -0
@@ -0,0 +1,92 @@
1
+ <template>
2
+ <label class="form-checkbox">
3
+ <CheckboxRoot
4
+ v-model="model"
5
+ :disabled="disabled"
6
+ :name="name"
7
+ :value="value"
8
+ class="form-checkbox-button"
9
+ >
10
+ <CheckboxIndicator class="form-checkbox-indicator">
11
+ <Icon type="check" />
12
+ </CheckboxIndicator>
13
+ </CheckboxRoot>
14
+ <span v-if="$slots.default"><slot /></span>
15
+ </label>
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ import { CheckboxIndicator, CheckboxRoot } from 'reka-ui'
20
+ import Icon from './Icon.vue'
21
+
22
+ const model = defineModel<boolean | 'indeterminate'>()
23
+
24
+ defineProps({
25
+ disabled: {
26
+ type: Boolean,
27
+ default: false,
28
+ },
29
+ name: {
30
+ type: String,
31
+ default: undefined,
32
+ },
33
+ value: {
34
+ type: String,
35
+ default: 'on',
36
+ },
37
+ })
38
+ </script>
39
+
40
+ <style scoped>
41
+ .form-checkbox {
42
+ display: flex;
43
+ align-items: center;
44
+ gap: var(--size-2);
45
+ cursor: pointer;
46
+ user-select: none;
47
+
48
+ &:hover .form-checkbox-button {
49
+ border-color: var(--primary);
50
+ }
51
+ }
52
+
53
+ .form-checkbox-button {
54
+ all: unset;
55
+ inline-size: var(--size-4);
56
+ block-size: var(--size-4);
57
+ border-radius: calc(var(--border-radius) / 2);
58
+ border: 2px solid var(--muted);
59
+ display: flex;
60
+ align-items: center;
61
+ justify-content: center;
62
+ transition: all var(--speed);
63
+ flex-shrink: 0;
64
+
65
+ &[data-state='checked'],
66
+ &[data-state='indeterminate'] {
67
+ border-color: var(--primary);
68
+ background: var(--primary);
69
+ }
70
+
71
+ &[data-disabled] {
72
+ opacity: 0.5;
73
+ cursor: not-allowed;
74
+ }
75
+
76
+ &:focus-visible {
77
+ outline: 2px solid var(--primary);
78
+ outline-offset: 2px;
79
+ }
80
+ }
81
+
82
+ .form-checkbox-indicator {
83
+ color: var(--background);
84
+ display: flex;
85
+ align-items: center;
86
+ justify-content: center;
87
+
88
+ .icon {
89
+ font-size: var(--font-xs);
90
+ }
91
+ }
92
+ </style>
@@ -0,0 +1,39 @@
1
+ <template>
2
+ <div
3
+ class="form-group"
4
+ :class="{ radio }"
5
+ >
6
+ <slot />
7
+ </div>
8
+ </template>
9
+
10
+ <script setup lang="ts">
11
+ defineProps<{
12
+ radio?: boolean
13
+ }>()
14
+ </script>
15
+
16
+ <style scoped>
17
+ .form-group {
18
+ display: grid;
19
+ gap: var(--spacer-sm);
20
+
21
+ &.radio {
22
+ display: flex;
23
+ gap: var(--spacer-sm);
24
+
25
+ & :deep(input) {
26
+ inline-size: min-content;
27
+
28
+ &:not(:first-of-type) {
29
+ margin-inline-start: var(--spacer-sm);
30
+ }
31
+ }
32
+
33
+ & :deep(label),
34
+ & :deep(input) {
35
+ display: inline;
36
+ }
37
+ }
38
+ }
39
+ </style>
@@ -0,0 +1,55 @@
1
+ <template>
2
+ <div class="input-group">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <style scoped>
8
+ .input-group {
9
+ position: relative;
10
+ display: flex;
11
+ align-items: center;
12
+
13
+ & :deep(input + .icon) {
14
+ position: absolute;
15
+ inset-inline-end: var(--ui-padding-inline);
16
+ inline-size: var(--size-4);
17
+ color: var(--muted);
18
+ z-index: 2;
19
+ }
20
+
21
+ & :deep(input:has(+ .icon)) {
22
+ padding-inline-end: calc(var(--ui-padding-inline) + var(--spacer-sm));
23
+
24
+ &:is(:hover, :active, :focus, .active) + .icon {
25
+ color: var(--gray-z-6);
26
+ }
27
+ }
28
+
29
+ & :deep(input),
30
+ & :deep(button),
31
+ & :deep(.button),
32
+ & :deep(a) {
33
+ z-index: 1;
34
+
35
+ &:has(+ input),
36
+ &:has(+ button),
37
+ &:has(+ a) {
38
+ border-start-end-radius: 0 !important;
39
+ border-end-end-radius: 0 !important;
40
+ }
41
+
42
+ + input,
43
+ + button,
44
+ + a {
45
+ margin-inline-start: calc(-1 * var(--border-width));
46
+ border-start-start-radius: 0 !important;
47
+ border-end-start-radius: 0 !important;
48
+ }
49
+
50
+ &:is(:hover, :active, :focus, .active) {
51
+ z-index: 2;
52
+ }
53
+ }
54
+ }
55
+ </style>
@@ -0,0 +1,89 @@
1
+ <template>
2
+ <div class="form-item">
3
+ <span
4
+ v-if="$slots.prefix"
5
+ class="prefix"
6
+ >
7
+ <slot name="prefix" />
8
+ </span>
9
+ <slot />
10
+ <span
11
+ v-if="$slots.suffix"
12
+ class="suffix"
13
+ >
14
+ <slot name="suffix" />
15
+ </span>
16
+ </div>
17
+ </template>
18
+
19
+ <style scoped>
20
+ @layer components {
21
+ .form-item {
22
+ border-radius: var(--border-radius);
23
+ display: flex;
24
+ align-items: center;
25
+ background: var(--background);
26
+ transition:
27
+ background-color var(--speed),
28
+ border-color var(--speed);
29
+ inline-size: 100%;
30
+ max-inline-size: -webkit-fill-available;
31
+
32
+ &:has(input:hover),
33
+ &:has(input:focus) {
34
+ background: var(--button-background-highlight);
35
+ border-color: var(--button-border-color-highlight);
36
+
37
+ .prefix,
38
+ .suffix {
39
+ background: var(--button-background-highlight);
40
+ box-shadow: var(--border-shadow-highlight);
41
+ }
42
+ }
43
+
44
+ .prefix,
45
+ .suffix {
46
+ padding: 0 var(--ui-padding-inline);
47
+ color: var(--muted);
48
+ background: var(--button-background);
49
+ transition: all var(--speed);
50
+ block-size: 100%;
51
+ display: flex;
52
+ align-items: center;
53
+ justify-content: center;
54
+ box-shadow: var(--border-shadow);
55
+ width: min-content;
56
+ }
57
+
58
+ .prefix {
59
+ border-start-start-radius: var(--border-radius);
60
+ border-end-start-radius: var(--border-radius);
61
+ }
62
+
63
+ .suffix {
64
+ border-start-end-radius: var(--border-radius);
65
+ border-end-end-radius: var(--border-radius);
66
+ }
67
+
68
+ &:has(> .prefix) {
69
+ border-start-start-radius: 0;
70
+ border-end-start-radius: 0;
71
+
72
+ & :deep(> :last-child) {
73
+ border-start-start-radius: 0;
74
+ border-end-start-radius: 0;
75
+ }
76
+ }
77
+
78
+ &:has(> .suffix) {
79
+ border-start-end-radius: 0;
80
+ border-end-end-radius: 0;
81
+
82
+ & :deep(> :first-child) {
83
+ border-start-end-radius: 0;
84
+ border-end-end-radius: 0;
85
+ }
86
+ }
87
+ }
88
+ }
89
+ </style>
@@ -0,0 +1,39 @@
1
+ <template>
2
+ <label class="form-label">
3
+ <span v-if="label">{{ label }}</span>
4
+ <slot />
5
+ </label>
6
+ </template>
7
+
8
+ <script setup lang="ts">
9
+ defineProps<{
10
+ label?: string
11
+ }>()
12
+ </script>
13
+
14
+ <style scoped>
15
+ .form-label {
16
+ font-family: var(--font-family);
17
+ font-size: var(--ui-font-size);
18
+ font-weight: var(--ui-font-weight);
19
+ text-transform: var(--ui-text-transform);
20
+ letter-spacing: var(--ui-letter-spacing);
21
+ line-height: var(--ui-line-height);
22
+ color: var(--ui-color);
23
+ transition: all var(--speed);
24
+ display: grid;
25
+ gap: var(--size-2);
26
+
27
+ &:hover {
28
+ color: var(--color);
29
+ }
30
+
31
+ & :deep(a) {
32
+ text-decoration: underline;
33
+ }
34
+
35
+ > span:first-child {
36
+ display: block;
37
+ }
38
+ }
39
+ </style>
@@ -0,0 +1,118 @@
1
+ <template>
2
+ <RadioGroupRoot
3
+ v-model="model"
4
+ :disabled="disabled"
5
+ :name="name"
6
+ :orientation="orientation"
7
+ class="form-radio-group"
8
+ >
9
+ <label
10
+ v-for="option in options"
11
+ :key="option[valueKey]"
12
+ class="form-radio-item"
13
+ >
14
+ <RadioGroupItem
15
+ :value="option[valueKey]"
16
+ class="form-radio-button"
17
+ >
18
+ <RadioGroupIndicator class="form-radio-indicator" />
19
+ </RadioGroupItem>
20
+ <span>{{ option[labelKey] }}</span>
21
+ </label>
22
+ </RadioGroupRoot>
23
+ </template>
24
+
25
+ <script setup lang="ts">
26
+ import { RadioGroupIndicator, RadioGroupItem, RadioGroupRoot } from 'reka-ui'
27
+
28
+ const model = defineModel<string>()
29
+
30
+ defineProps({
31
+ options: {
32
+ type: Array as () => Record<string, any>[],
33
+ default: () => [],
34
+ },
35
+ disabled: {
36
+ type: Boolean,
37
+ default: false,
38
+ },
39
+ orientation: {
40
+ type: String as () => 'horizontal' | 'vertical',
41
+ default: 'horizontal',
42
+ },
43
+ valueKey: {
44
+ type: String,
45
+ default: 'value',
46
+ },
47
+ labelKey: {
48
+ type: String,
49
+ default: 'label',
50
+ },
51
+ name: {
52
+ type: String,
53
+ default: undefined,
54
+ },
55
+ })
56
+ </script>
57
+
58
+ <style scoped>
59
+ .form-radio-group {
60
+ display: flex;
61
+ gap: var(--spacer);
62
+
63
+ &[data-orientation='vertical'] {
64
+ flex-direction: column;
65
+ gap: var(--spacer-sm);
66
+ }
67
+
68
+ &[data-disabled] {
69
+ opacity: 0.5;
70
+ cursor: not-allowed;
71
+ }
72
+ }
73
+
74
+ .form-radio-item {
75
+ display: flex;
76
+ align-items: center;
77
+ gap: var(--size-2);
78
+ cursor: pointer;
79
+ user-select: none;
80
+
81
+ &:hover .form-radio-button {
82
+ border-color: var(--primary);
83
+ }
84
+ }
85
+
86
+ .form-radio-button {
87
+ all: unset;
88
+ inline-size: var(--size-4);
89
+ block-size: var(--size-4);
90
+ border-radius: 50%;
91
+ border: 2px solid var(--muted);
92
+ display: flex;
93
+ align-items: center;
94
+ justify-content: center;
95
+ transition: border-color var(--speed);
96
+ flex-shrink: 0;
97
+
98
+ &[data-state='checked'] {
99
+ border-color: var(--primary);
100
+ }
101
+
102
+ &[data-disabled] {
103
+ cursor: not-allowed;
104
+ }
105
+
106
+ &:focus-visible {
107
+ outline: 2px solid var(--primary);
108
+ outline-offset: 2px;
109
+ }
110
+ }
111
+
112
+ .form-radio-indicator {
113
+ inline-size: var(--size-2);
114
+ block-size: var(--size-2);
115
+ border-radius: 50%;
116
+ background: var(--primary);
117
+ }
118
+ </style>
@@ -0,0 +1,160 @@
1
+ <template>
2
+ <SelectRoot
3
+ v-model="model"
4
+ :multiple="multiple"
5
+ :disabled="disabled"
6
+ :name="name"
7
+ >
8
+ <SelectTrigger class="form-select-trigger">
9
+ <SelectValue :placeholder="placeholder" />
10
+ <SelectIcon class="form-select-icon">
11
+ <Icon type="chevron-down" />
12
+ </SelectIcon>
13
+ </SelectTrigger>
14
+
15
+ <SelectPortal>
16
+ <SelectContent
17
+ position="popper"
18
+ :side-offset="4"
19
+ class="form-select-content"
20
+ >
21
+ <SelectViewport class="form-select-viewport">
22
+ <SelectItem
23
+ v-for="option in options"
24
+ :key="option[valueKey]"
25
+ :value="option[valueKey]"
26
+ class="form-select-item"
27
+ >
28
+ <SelectItemText>{{ option[labelKey] }}</SelectItemText>
29
+ <SelectItemIndicator class="form-select-indicator">
30
+ <Icon type="check" />
31
+ </SelectItemIndicator>
32
+ </SelectItem>
33
+ </SelectViewport>
34
+ </SelectContent>
35
+ </SelectPortal>
36
+ </SelectRoot>
37
+ </template>
38
+
39
+ <script setup lang="ts">
40
+ import {
41
+ SelectContent,
42
+ SelectIcon,
43
+ SelectItem,
44
+ SelectItemIndicator,
45
+ SelectItemText,
46
+ SelectPortal,
47
+ SelectRoot,
48
+ SelectTrigger,
49
+ SelectValue,
50
+ SelectViewport,
51
+ } from 'reka-ui'
52
+ import Icon from './Icon.vue'
53
+
54
+ const model = defineModel<string | string[]>()
55
+
56
+ defineProps({
57
+ options: {
58
+ type: Array as () => Record<string, any>[],
59
+ default: () => [],
60
+ },
61
+ placeholder: {
62
+ type: String,
63
+ default: 'Select...',
64
+ },
65
+ multiple: {
66
+ type: Boolean,
67
+ default: false,
68
+ },
69
+ disabled: {
70
+ type: Boolean,
71
+ default: false,
72
+ },
73
+ valueKey: {
74
+ type: String,
75
+ default: 'value',
76
+ },
77
+ labelKey: {
78
+ type: String,
79
+ default: 'label',
80
+ },
81
+ name: {
82
+ type: String,
83
+ default: undefined,
84
+ },
85
+ })
86
+ </script>
87
+
88
+ <style scoped>
89
+ .form-select-trigger {
90
+ background: var(--background);
91
+ color: var(--color);
92
+ inline-size: 100%;
93
+ align-items: center;
94
+ justify-content: space-between;
95
+ gap: var(--size-2);
96
+ cursor: pointer;
97
+
98
+ &[data-placeholder] {
99
+ color: var(--muted);
100
+ }
101
+
102
+ &[data-disabled] {
103
+ cursor: not-allowed;
104
+ opacity: 0.5;
105
+ }
106
+ }
107
+
108
+ .form-select-icon {
109
+ color: var(--muted);
110
+ transition: transform var(--speed);
111
+
112
+ [data-state='open'] > & {
113
+ transform: rotate(180deg);
114
+ }
115
+ }
116
+
117
+ :global(.form-select-content) {
118
+ background: var(--background);
119
+ border: var(--border);
120
+ border-radius: var(--border-radius);
121
+ box-shadow: var(--shadow-lg);
122
+ z-index: var(--z-index-dropdown);
123
+ min-width: var(--reka-select-trigger-width);
124
+ max-height: var(--reka-select-content-available-height);
125
+ overflow: hidden;
126
+ }
127
+
128
+ :global(.form-select-viewport) {
129
+ padding: var(--size-1);
130
+ }
131
+
132
+ :global(.form-select-item) {
133
+ padding: var(--size-2) var(--size-3);
134
+ border-radius: calc(var(--border-radius) / 2);
135
+ display: flex;
136
+ align-items: center;
137
+ justify-content: space-between;
138
+ gap: var(--size-2);
139
+ cursor: pointer;
140
+ outline: none;
141
+ user-select: none;
142
+
143
+ &[data-highlighted] {
144
+ background: var(--button-background-highlight);
145
+ }
146
+
147
+ &[data-state='checked'] {
148
+ font-weight: 500;
149
+ }
150
+
151
+ &[data-disabled] {
152
+ opacity: 0.5;
153
+ cursor: not-allowed;
154
+ }
155
+ }
156
+
157
+ :global(.form-select-indicator) {
158
+ color: var(--accent);
159
+ }
160
+ </style>
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <textarea
3
+ ref="textarea"
4
+ v-model="model"
5
+ :rows="rows"
6
+ v-bind="$attrs"
7
+ @input="resize"
8
+ />
9
+ </template>
10
+
11
+ <script setup lang="ts">
12
+ import { useTemplateRef, onMounted } from 'vue'
13
+
14
+ const model = defineModel<string>()
15
+
16
+ const { rows = 4 } = defineProps<{
17
+ rows?: number
18
+ }>()
19
+
20
+ const textarea = useTemplateRef('textarea')
21
+
22
+ function resize() {
23
+ const el = textarea.value
24
+ if (!el) return
25
+ el.style.height = 'auto'
26
+ el.style.height = `${el.scrollHeight}px`
27
+ }
28
+
29
+ onMounted(resize)
30
+ </script>
31
+
32
+ <style scoped>
33
+ textarea {
34
+ resize: none;
35
+ block-size: auto;
36
+ overflow: hidden;
37
+ }
38
+ </style>
@@ -0,0 +1,29 @@
1
+ <template>
2
+ <IconifyIcon
3
+ v-if="resolvedIcon"
4
+ :icon="resolvedIcon"
5
+ class="icon"
6
+ />
7
+ </template>
8
+
9
+ <script setup lang="ts">
10
+ import { computed, inject } from 'vue'
11
+ import { Icon as IconifyIcon } from '@iconify/vue'
12
+ import { IconAliasesKey, defaultIconAliases } from '../icons'
13
+
14
+ const props = defineProps<{ type: string }>()
15
+
16
+ const aliases = inject(IconAliasesKey, defaultIconAliases)
17
+
18
+ const resolvedIcon = computed(() => aliases[props.type] || props.type)
19
+ </script>
20
+
21
+ <style scoped>
22
+ .icon {
23
+ display: inline-flex;
24
+ width: 1em;
25
+ height: 1em;
26
+ align-items: center;
27
+ justify-content: center;
28
+ }
29
+ </style>