design-system-dashboard-devmunity 0.4.0 → 1.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 (53) hide show
  1. package/README.md +33 -31
  2. package/app/app.config.ts +2 -1
  3. package/app/app.vue +21 -3
  4. package/app/assets/css/themes/components/input.js +5 -0
  5. package/app/assets/css/themes/index.js +1 -0
  6. package/app/components/BaseButton.vue +3 -0
  7. package/app/components/Colors.mdx +42 -0
  8. package/app/components/Indroduction.mdx +100 -0
  9. package/app/components/a/button/a-button-avatar-dropdown.stories.ts +83 -0
  10. package/app/components/a/button/a-button-avatar-dropdown.vue +41 -17
  11. package/app/components/a/button/a-button-navigation.stories.ts +66 -0
  12. package/app/components/a/button/a-button-navigation.vue +57 -0
  13. package/app/components/a/card/a-card-inner.stories.ts +89 -0
  14. package/app/components/a/card/a-card-inner.vue +26 -13
  15. package/app/components/a/dropdown/a-dropdown-avatar.stories.ts +160 -0
  16. package/app/components/a/dropdown/a-dropdown-avatar.vue +75 -33
  17. package/app/components/a/pill/a-pill.stories.ts +91 -0
  18. package/app/components/a/pill/a-pill.vue +63 -42
  19. package/app/components/b/badge/b-badge.stories.ts +77 -0
  20. package/app/components/b/badge/b-badge.vue +43 -19
  21. package/app/components/b/card/b-card.stories.ts +120 -0
  22. package/app/components/b/card/b-card.vue +49 -32
  23. package/app/components/b/modal/b-modal.stories.ts +210 -0
  24. package/app/components/b/modal/b-modal.vue +125 -81
  25. package/app/components/c/badge/c-badge-status.stories.ts +72 -0
  26. package/app/components/c/badge/c-badge-status.vue +36 -15
  27. package/app/components/c/modal/c-modal-danger.stories.ts +112 -0
  28. package/app/components/c/modal/c-modal-danger.vue +60 -41
  29. package/app/components/d/action-buttons/d-action-buttons.stories.ts +90 -0
  30. package/app/components/d/action-buttons/d-action-buttons.vue +121 -0
  31. package/app/components/d/card/d-card-header.stories.ts +123 -0
  32. package/app/components/d/card/d-card-header.vue +59 -41
  33. package/app/components/d/upload/d-upload-avatar.stories.ts +66 -0
  34. package/app/components/d/upload/d-upload-avatar.vue +49 -30
  35. package/app/types/index.ts +1 -0
  36. package/app/types/semantic-colors.type.ts +3 -0
  37. package/app/utils/util-get-colors-from-css.ts +53 -0
  38. package/nuxt.config.ts +11 -16
  39. package/package.json +84 -68
  40. package/.editorconfig +0 -13
  41. package/.github/workflows/release.yml +0 -36
  42. package/.husky/commit-msg +0 -1
  43. package/.husky/pre-commit +0 -0
  44. package/.prettierrc +0 -24
  45. package/.storybook/main.js +0 -25
  46. package/.storybook/preview.js +0 -13
  47. package/.vscode/settings.json +0 -28
  48. package/CHANGELOG.md +0 -55
  49. package/app/Introduction.mdx +0 -44
  50. package/app/components/a/button/a-button-back.vue +0 -33
  51. package/app/components/d/d-action-buttons.vue +0 -99
  52. package/commitlint.config.js +0 -8
  53. package/tsconfig.json +0 -8
@@ -1,84 +1,120 @@
1
- <script lang="jsx" setup>
2
- import { resolveComponent } from 'vue'
3
- import { twMerge } from 'tailwind-merge'
4
-
5
- const UForm = resolveComponent('UForm')
6
-
7
- const props = defineProps({
8
- state: {
9
- type: Object,
10
- default: null,
11
- required: false,
12
- },
13
- schema: {
14
- type: Object,
15
- default: null,
16
- required: false,
17
- },
18
- title: {
19
- type: String,
20
- default: '',
21
- required: true,
22
- },
23
- description: {
24
- type: String,
25
- default: '',
26
- required: true,
27
- },
28
- text: {
29
- type: String,
30
- default: '',
31
- required: false,
32
- },
33
- primaryButtonText: {
34
- type: String,
35
- default: 'Guardar',
36
- required: false,
37
- },
38
- primaryButtonColor: {
39
- type: String,
40
- default: 'primary',
41
- required: true,
42
- },
43
- secondaryButtonText: {
44
- type: String,
45
- default: 'Cancelar',
46
- required: false,
47
- },
48
- hasFooter: {
49
- type: Boolean,
50
- default: true,
51
- required: false,
52
- },
53
- isPrimaryButtonDisabled: {
54
- type: Boolean,
55
- default: false,
56
- required: false,
57
- },
58
- hasButtonsBlock: {
59
- type: Boolean,
60
- default: false,
61
- required: false,
62
- },
63
- classButtons: {
64
- type: String,
65
- default: '',
66
- required: false,
67
- },
1
+ <script lang="ts" setup>
2
+ import { resolveComponent, computed, type Ref } from 'vue'
3
+ import { twMerge, type ClassNameValue } from 'tailwind-merge'
4
+ import type { UForm, UModal } from '#components'
5
+ import type {SemanticColors } from '@/types'
6
+
7
+ const UFormComponent = resolveComponent('UForm')
8
+
9
+ interface Props {
10
+ /**
11
+ * The state object for form management
12
+ */
13
+ state?: Record<string, any> | null
14
+ /**
15
+ * The schema for form validation
16
+ */
17
+ schema?: Record<string, any> | null
18
+ /**
19
+ * The title of the modal
20
+ */
21
+ title?: string
22
+ /**
23
+ * The description of the modal
24
+ */
25
+ description?: string
26
+ /**
27
+ * Text for the main content when it is not necessary to use the slot with more complex markup
28
+ */
29
+ text?: string
30
+ /**
31
+ * Text for the primary button
32
+ */
33
+ primaryButtonText?: string
34
+ /**
35
+ * Color variant for the primary button
36
+ */
37
+ primaryButtonColor?: SemanticColors
38
+ /**
39
+ * Text for the secondary button
40
+ */
41
+ secondaryButtonText?: string
42
+ /**
43
+ * Whether the modal has a footer
44
+ */
45
+ hasFooter?: boolean
46
+ /**
47
+ * Whether the primary button is disabled
48
+ */
49
+ isPrimaryButtonDisabled?: boolean
50
+ /**
51
+ * Whether buttons should be displayed as blocks
52
+ */
53
+ hasButtonsBlock?: boolean
54
+ /**
55
+ * Additional CSS classes for buttons
56
+ */
57
+ classButtons?: ClassNameValue
58
+ /**
59
+ * Additional CSS classes for the modal
60
+ */
61
+ class?: ClassNameValue
62
+ }
63
+
64
+ const props = withDefaults(defineProps<Props>(), {
65
+ state: null,
66
+ schema: null,
67
+ title: '',
68
+ description: '',
69
+ text: '',
70
+ primaryButtonText: 'Guardar',
71
+ primaryButtonColor: 'primary',
72
+ secondaryButtonText: 'Cancelar',
73
+ hasFooter: true,
74
+ isPrimaryButtonDisabled: false,
75
+ hasButtonsBlock: false,
76
+ classButtons: '',
77
+ class: '',
68
78
  })
69
79
 
70
- const emit = defineEmits(['on-click-primary-button', 'on-click-secondary-button', 'on-submit'])
80
+ const emit = defineEmits<{
81
+ /**
82
+ * Emitted when the primary button is clicked
83
+ */
84
+ (e: 'on-click-primary-button'): void
85
+ /**
86
+ * Emitted when the secondary button is clicked
87
+ */
88
+ (e: 'on-click-secondary-button'): void
89
+ /**
90
+ * Emitted when the form is submitted
91
+ */
92
+ (e: 'on-submit'): void
93
+ }>()
94
+
95
+ defineSlots<{
96
+ /**
97
+ * Custom header content
98
+ */
99
+ header?(): any
100
+ /**
101
+ * Default body content when no text is provided
102
+ */
103
+ default?(): any
104
+ /**
105
+ * Custom footer content
106
+ */
107
+ footer?(): any
108
+ }>()
71
109
 
72
110
  // Model
73
111
 
74
- const isOpen = defineModel({
75
- type: Boolean,
112
+ const isOpen = defineModel<boolean>({
76
113
  default: false,
77
114
  required: true,
78
115
  })
79
- const formRef = defineModel('formRef', {
80
- type: Object,
81
- default: () => {},
116
+ const formRef = defineModel<Ref<any>>('formRef', {
117
+ default: () => ({}) as any,
82
118
  required: false,
83
119
  })
84
120
 
@@ -96,32 +132,40 @@ const formRef = defineModel('formRef', {
96
132
  // })
97
133
 
98
134
  const formProps = computed(() => {
99
- // return props.data ? { ref: 'form', state: props.data, onSubmit: handleSubmit } : {}
100
135
  return props.state ? { ref: 'formRef', state: props.state, schema: props.schema } : {}
101
136
  })
102
137
 
103
138
  // Methods
104
139
 
105
- function handleSubmit() {
140
+ function handleSubmit(): void {
106
141
  emit('on-submit')
107
142
  }
108
- function handleClickPrimaryButton() {
143
+ function handleClickPrimaryButton(): void {
109
144
  emit('on-click-primary-button')
110
145
  }
111
- function handleClickSecondaryButton() {
146
+ function handleClickSecondaryButton(): void {
112
147
  isOpen.value = false
113
148
  emit('on-click-secondary-button')
114
149
  }
115
150
  </script>
116
151
 
117
152
  <template>
118
- <UModal v-model:open="isOpen" :title="title" :description="description">
153
+ <UModal
154
+ v-model:open="isOpen"
155
+ :title="title"
156
+ :description="description"
157
+ :class="twMerge('w-lg', props.class)"
158
+ >
119
159
  <template #header>
120
160
  <slot v-if="$slots.header" name="header" />
121
161
  </template>
122
162
 
123
163
  <template #body>
124
- <component :is="state ? UForm : 'section'" v-bind="formProps" @submit="handleSubmit">
164
+ <component
165
+ :is="props.state ? UFormComponent : 'section'"
166
+ v-bind="formProps"
167
+ @submit="handleSubmit"
168
+ >
125
169
  <p v-if="text">
126
170
  {{ text }}
127
171
  </p>
@@ -136,9 +180,9 @@ function handleClickSecondaryButton() {
136
180
  :primary-button-color="primaryButtonColor"
137
181
  :primary-button-text="primaryButtonText"
138
182
  :secondary-button-text="secondaryButtonText"
139
- :is-buttons-block="hasButtonsBlock"
183
+ :has-buttons-block="hasButtonsBlock"
140
184
  :is-primary-button-disabled="isPrimaryButtonDisabled"
141
- :class="twMerge('flex w-full justify-end gap-x-2', classButtons)"
185
+ :class="twMerge('flex w-full justify-end gap-x-2', props.classButtons)"
142
186
  class-buttons="w-40"
143
187
  @on-click-primary-button="handleClickPrimaryButton"
144
188
  @on-click-secondary-button="handleClickSecondaryButton"
@@ -0,0 +1,72 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import CBadgeStatus from './c-badge-status.vue'
3
+
4
+ const meta = {
5
+ title: 'Composites/Badge/CBadgeStatus',
6
+ component: CBadgeStatus,
7
+ parameters: {
8
+ docs: {
9
+ description: {
10
+ component:
11
+ 'Badge component variant of [CBadge](/docs/bases-badge-bbadge--docs), specifically for displaying the status of a task.',
12
+ },
13
+ },
14
+ },
15
+ argTypes: {
16
+ value: {
17
+ control: { type: 'select' },
18
+ options: ['TODO', 'IN_PROGRESS', 'FINISHED', 'CANCELLED', 'OTHER'] satisfies string[],
19
+ },
20
+ },
21
+ } satisfies Meta<typeof CBadgeStatus>
22
+
23
+ export default meta
24
+
25
+ type Story = StoryObj<typeof meta>
26
+
27
+ export const Default: Story = {
28
+ args: {
29
+ label: 'Status',
30
+ value: 'OTHER',
31
+ },
32
+ }
33
+
34
+ export const Todo: Story = {
35
+ args: {
36
+ ...Default.args,
37
+ label: 'Todo',
38
+ value: 'TODO',
39
+ },
40
+ }
41
+
42
+ export const InProgress: Story = {
43
+ args: {
44
+ ...Default.args,
45
+ label: 'In progress',
46
+ value: 'IN_PROGRESS',
47
+ },
48
+ }
49
+
50
+ export const Finished: Story = {
51
+ args: {
52
+ ...Default.args,
53
+ label: 'Finished',
54
+ value: 'FINISHED',
55
+ },
56
+ }
57
+
58
+ export const Cancelled: Story = {
59
+ args: {
60
+ ...Default.args,
61
+ label: 'Cancelled',
62
+ value: 'CANCELLED',
63
+ },
64
+ }
65
+
66
+ export const Other: Story = {
67
+ args: {
68
+ ...Default.args,
69
+ label: 'Other',
70
+ value: 'OTHER',
71
+ },
72
+ }
@@ -1,25 +1,38 @@
1
- <script setup>
2
- const props = defineProps({
3
- label: {
4
- type: String,
5
- default: '',
6
- required: true,
7
- },
8
- value: {
9
- type: String,
10
- default: '',
11
- required: true,
12
- },
1
+ <script lang="ts" setup>
2
+ import type { BBadge } from '#components'
3
+
4
+ type BadgeStyles = InstanceType<typeof BBadge>['$props']['styles']
5
+ type DefaultStyle = InstanceType<typeof BBadge>['$props']['defaultStyle']
6
+
7
+ interface Props {
8
+ /**
9
+ * The label text to display on the badge
10
+ */
11
+ label: string
12
+ /**
13
+ * The status value that determines the badge style
14
+ */
15
+ value: string
16
+ }
17
+
18
+ const props = withDefaults(defineProps<Props>(), {
19
+ label: '',
20
+ value: '',
13
21
  })
14
22
 
15
- const styles = {
16
- PLANNED: {
23
+ const styles: BadgeStyles = {
24
+ TODO: {
17
25
  color: 'accent',
18
26
  variant: 'soft',
19
27
  },
28
+ IN_PROGRESS: {
29
+ color: 'secondary',
30
+ variant: 'soft',
31
+ },
20
32
  FINISHED: {
21
33
  color: 'success',
22
34
  variant: 'soft',
35
+ icon: 'material-symbols:check-circle-outline',
23
36
  },
24
37
  CANCELLED: {
25
38
  color: 'error',
@@ -31,7 +44,15 @@ const styles = {
31
44
  variant: 'soft',
32
45
  },
33
46
  }
34
- const defaultStyle = styles.OTHER
47
+
48
+ const defaultStyle: DefaultStyle = styles.OTHER
49
+
50
+ defineSlots<{
51
+ /**
52
+ * The default slot content
53
+ */
54
+ default(): any
55
+ }>()
35
56
  </script>
36
57
 
37
58
  <template>
@@ -0,0 +1,112 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import { fn } from '@storybook/test'
3
+ import CModalDanger from './c-modal-danger.vue'
4
+ import UButton from '@nuxt/ui/components/Button.vue'
5
+
6
+ const meta = {
7
+ title: 'Composites/Modal/CModalDanger',
8
+ component: CModalDanger,
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component:
13
+ 'Modal component variant of [BModal](/docs/bases-modal-bmodal--docs), specifically for displaying a danger modal. It displays the footer buttons in block mode by default, and the main action button in "error" color.',
14
+ },
15
+ },
16
+ },
17
+ argTypes: {
18
+ 'onOn-click-primary-button': {
19
+ table: { disable: true },
20
+ },
21
+ 'onOn-click-secondary-button': {
22
+ table: { disable: true },
23
+ },
24
+ modelValue: {
25
+ control: 'boolean',
26
+ name: 'isOpen',
27
+ description: 'Whether the modal is open',
28
+ },
29
+ },
30
+ args: {
31
+ 'onOn-click-primary-button': fn(),
32
+ 'onOn-click-secondary-button': fn(),
33
+ },
34
+ render: (args) =>
35
+ ({
36
+ components: { CModalDanger, UButton },
37
+ setup() {
38
+ return { args }
39
+ },
40
+ template: `
41
+ <div>
42
+ <UButton label="Open Danger Modal" color="error" @click="args.modelValue=true" icon="i-lucide-trash" />
43
+
44
+ <CModalDanger v-bind="args" v-model="args.modelValue" />
45
+ </div>
46
+ `,
47
+ }) as any,
48
+ } satisfies Meta<typeof CModalDanger>
49
+
50
+ export default meta
51
+
52
+ type Story = StoryObj<typeof meta>
53
+
54
+ export const Default: Story = {
55
+ args: {
56
+ title: 'Delete Item',
57
+ description: 'Are you sure you want to delete this item?',
58
+ modelValue: false,
59
+ text: 'This action is irreversible and cannot be undone.',
60
+ },
61
+ }
62
+
63
+ export const CustomButtonsLabels: Story = {
64
+ args: {
65
+ ...Default.args,
66
+ title: 'Destructive Action',
67
+ description: 'Proceed with caution',
68
+ modelValue: false,
69
+ primaryButtonText: 'Destroy',
70
+ secondaryButtonText: 'Abort',
71
+ text: 'Custom button labels example.',
72
+ },
73
+ }
74
+
75
+ export const WithSlot: Story = {
76
+ args: {
77
+ title: 'Custom Content',
78
+ description: 'Modal with custom slot content',
79
+ modelValue: false,
80
+ },
81
+ render: (args) =>
82
+ ({
83
+ components: { CModalDanger, UButton },
84
+ setup() {
85
+ return { args }
86
+ },
87
+ template: `
88
+ <div>
89
+ <UButton label="Open Danger Slot Modal" color="error" @click="args.modelValue=true" icon="i-lucide-trash" />
90
+
91
+ <CModalDanger v-bind="args" v-model="args.modelValue">
92
+ <div class="space-y-4">
93
+ <div class="p-4 bg-red-50 border border-red-200 rounded-lg">
94
+ <h4 class="text-red-800 font-semibold mb-2">Warning Details</h4>
95
+ <ul class="text-sm text-red-700 space-y-1">
96
+ <li>• All associated data will be permanently deleted</li>
97
+ <li>• This action cannot be reversed</li>
98
+ <li>• Other users may be affected</li>
99
+ </ul>
100
+ </div>
101
+ <div class="flex items-center space-x-2">
102
+ <input type="checkbox" id="confirm" class="rounded">
103
+ <label for="confirm" class="text-sm text-gray-600">
104
+ I understand the consequences
105
+ </label>
106
+ </div>
107
+ </div>
108
+ </CModalDanger>
109
+ </div>
110
+ `,
111
+ }) as any,
112
+ }
@@ -1,48 +1,66 @@
1
- <script lang="jsx" setup>
2
- const props = defineProps({
3
- state: {
4
- type: Object,
5
- default: null,
6
- required: false,
7
- },
8
- schema: {
9
- type: Object,
10
- default: null,
11
- required: false,
12
- },
13
- title: {
14
- type: String,
15
- default: '',
16
- required: true,
17
- },
18
- description: {
19
- type: String,
20
- default: '',
21
- required: true,
22
- },
23
- text: {
24
- type: String,
25
- default: '',
26
- required: false,
27
- },
28
- primaryButtonText: {
29
- type: String,
30
- default: 'Eliminar',
31
- required: false,
32
- },
33
- secondaryButtonText: {
34
- type: String,
35
- default: 'Cancelar',
36
- required: false,
37
- },
1
+ <script lang="ts" setup>
2
+ import type { BModal } from '#components'
3
+
4
+ interface Props {
5
+ /**
6
+ * The state object for form management
7
+ */
8
+ state?: Record<string, any> | null
9
+ /**
10
+ * The schema for form validation
11
+ */
12
+ schema?: Record<string, any> | null
13
+ /**
14
+ * The title of the modal
15
+ */
16
+ title: string
17
+ /**
18
+ * The description of the modal
19
+ */
20
+ description: string
21
+ /**
22
+ * Text for the main content when it is not necessary to use the slot with more complex markup
23
+ */
24
+ text?: string
25
+ /**
26
+ * Text for the primary button
27
+ */
28
+ primaryButtonText?: string
29
+ /**
30
+ * Text for the secondary button
31
+ */
32
+ secondaryButtonText?: string
33
+ }
34
+
35
+ const props = withDefaults(defineProps<Props>(), {
36
+ state: null,
37
+ schema: null,
38
+ text: '',
39
+ primaryButtonText: 'Eliminar',
40
+ secondaryButtonText: 'Cancelar',
38
41
  })
39
42
 
40
- const emit = defineEmits(['on-click-primary-button', 'on-click-secondary-button'])
43
+ const emit = defineEmits<{
44
+ /**
45
+ * Emitted when the primary button is clicked
46
+ */
47
+ (e: 'on-click-primary-button'): void
48
+ /**
49
+ * Emitted when the secondary button is clicked
50
+ */
51
+ (e: 'on-click-secondary-button'): void
52
+ }>()
53
+
54
+ defineSlots<{
55
+ /**
56
+ * Default body content when no text is provided
57
+ */
58
+ default?(): any
59
+ }>()
41
60
 
42
61
  // Model
43
62
 
44
- const isOpen = defineModel({
45
- type: Boolean,
63
+ const isOpen = defineModel<boolean>({
46
64
  default: false,
47
65
  required: true,
48
66
  })
@@ -52,13 +70,14 @@ const isOpen = defineModel({
52
70
  <BModal
53
71
  v-model="isOpen"
54
72
  :title="title"
73
+ :description="description"
55
74
  :text="text"
56
75
  :primary-button-text="primaryButtonText"
57
76
  :secondary-button-text="secondaryButtonText"
58
77
  :state="state"
59
78
  :schema="schema"
60
79
  primary-button-color="error"
61
- is-block-buttons
80
+ has-buttons-block
62
81
  @on-click-primary-button="emit('on-click-primary-button')"
63
82
  @on-click-secondary-button="emit('on-click-secondary-button')"
64
83
  >