srcdev-nuxt-forms 2.1.13 → 2.1.14

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 (51) hide show
  1. package/assets/styles/forms/themes/_error.css +14 -0
  2. package/assets/styles/forms/themes/_ghost.css +14 -0
  3. package/assets/styles/forms/themes/_primary.css +15 -1
  4. package/assets/styles/forms/themes/_secondary.css +14 -0
  5. package/assets/styles/forms/themes/_success.css +14 -0
  6. package/assets/styles/forms/themes/_tertiary.css +14 -0
  7. package/assets/styles/forms/themes/_warning.css +14 -0
  8. package/assets/styles/forms/variables/_theme.css +3 -0
  9. package/assets/styles/main.css +1 -0
  10. package/assets/styles/typography/index.css +2 -0
  11. package/assets/styles/{variables/_typography.css → typography/utils/_classes.css} +0 -16
  12. package/assets/styles/typography/utils/_weights.css +69 -0
  13. package/assets/styles/typography/utils/index.css +2 -0
  14. package/assets/styles/typography/variables/_reponsive-font-size.css +10 -0
  15. package/assets/styles/typography/variables/index.css +2 -0
  16. package/assets/styles/variables/index.css +1 -3
  17. package/components/forms/c12/prop-validators/index.ts +24 -1
  18. package/components/forms/form-errors/InputError.vue +7 -3
  19. package/components/forms/form-errors/stories/InputError.stories.ts +36 -0
  20. package/components/forms/form-errors/tests/InputError.spec.ts +67 -0
  21. package/components/forms/input-button/InputButtonCore.vue +7 -5
  22. package/components/forms/input-button/stories/InputButtonCore.mdx +8 -0
  23. package/components/forms/input-button/stories/InputButtonCore.stories.ts +65 -0
  24. package/components/forms/input-button/variants/InputButtonConfirm.vue +5 -5
  25. package/components/forms/input-button/variants/InputButtonSubmit.vue +4 -16
  26. package/components/forms/input-checkbox/variants/MultipleCheckboxes.vue +39 -6
  27. package/components/forms/input-checkbox/variants/SingleCheckbox.vue +3 -3
  28. package/components/forms/input-checkbox-radio/InputCheckboxRadioButton.vue +130 -0
  29. package/components/forms/{input-checkbox/InputCheckboxCore.vue → input-checkbox-radio/InputCheckboxRadioCore.vue} +46 -14
  30. package/components/forms/{input-checkbox/InputCheckboxWithLabel.vue → input-checkbox-radio/InputCheckboxRadioWithLabel.vue} +12 -8
  31. package/components/forms/input-number/variants/InputNumberDefault.vue +1 -1
  32. package/components/forms/input-radio/variants/MultipleRadiobuttons.vue +39 -4
  33. package/components/forms/input-range/InputRangeCore.vue +32 -0
  34. package/components/forms/input-range/variants/InputRangeDefault.vue +1 -1
  35. package/components/forms/input-range-fancy/InputRangeFancyCore.vue +2 -2
  36. package/components/forms/input-range-fancy/InputRangeFancyWithLabel.vue +1 -1
  37. package/components/forms/input-text/InputTextCore.vue +5 -1
  38. package/components/forms/input-text/stories/InputTextCore.mdx +8 -0
  39. package/components/forms/input-text/stories/InputTextCore.stories.ts +59 -0
  40. package/components/forms/input-text/variants/{material/InputPasswordWithLabel.vue → InputPasswordWithLabel.vue} +1 -1
  41. package/components/forms/input-text/variants/{material/InputTextAsNumberWithLabel.vue → InputTextAsNumberWithLabel.vue} +2 -2
  42. package/components/forms/input-text/variants/{material/InputTextWithLabel.vue → InputTextWithLabel.vue} +2 -2
  43. package/components/forms/input-text/variants/stories/InputPasswordWithLabel.mdx +8 -0
  44. package/components/forms/input-text/variants/stories/InputPasswordWithLabel.stories.ts +60 -0
  45. package/components/forms/input-textarea/variants/InputTextareaWithLabel.vue +1 -1
  46. package/nuxt.config.ts +11 -4
  47. package/package.json +17 -4
  48. package/components/forms/input-radio/InputRadiobuttonCore.vue +0 -170
  49. package/components/forms/input-radio/InputRadiobuttonWithLabel.vue +0 -93
  50. /package/assets/styles/{variables/_default.css → typography/variables/_colors.css} +0 -0
  51. /package/assets/styles/variables/colors/{index.css → colors.css} +0 -0
@@ -0,0 +1,8 @@
1
+ import { Meta, Canvas, Controls } from '@storybook/blocks';
2
+ import * as InputPasswordWithLabelStories from './InputPasswordWithLabel.stories'
3
+
4
+ <Meta of={InputPasswordWithLabelStories} />
5
+
6
+ <Canvas of={InputPasswordWithLabelStories.Primary} />
7
+
8
+ <Controls of={InputPasswordWithLabelStories.Primary} />
@@ -0,0 +1,60 @@
1
+ import type { Meta, StoryFn } from '@nuxtjs/storybook';
2
+ import InputPasswordWithLabel from '../InputPasswordWithLabel.vue';
3
+ import propValidators from '../../../c12/prop-validators';
4
+
5
+ export default {
6
+ title: 'Components/Forms/Input/Text/InputPasswordWithLabel',
7
+ component: InputPasswordWithLabel,
8
+ argTypes: {
9
+ type: {
10
+ options: propValidators.inputTypesText,
11
+ control: { type: 'select' },
12
+ },
13
+ inputMode: {
14
+ options: propValidators.inputMode,
15
+ control: { type: 'select' },
16
+ },
17
+ theme: {
18
+ options: propValidators.theme,
19
+ control: { type: 'select' },
20
+ default: 'primary',
21
+ },
22
+ },
23
+ } as Meta<typeof InputPasswordWithLabel>;
24
+
25
+ const Template: StoryFn<typeof InputPasswordWithLabel> = (args) => ({
26
+ components: { InputPasswordWithLabel },
27
+ setup() {
28
+ return { args };
29
+ },
30
+ template: `
31
+ <Suspense>
32
+ <template #default>
33
+ <InputPasswordWithLabel v-bind="args">
34
+ <template v-if="${'iconOnly' in args}" v-slot:iconOnly>${args.iconOnly}</template>
35
+ </InputPasswordWithLabel>
36
+ </template>
37
+ <template #fallback>
38
+ <div>Loading...</div>
39
+ </template>
40
+ </Suspense>
41
+ `,
42
+ // template: '<InputPasswordWithLabel v-bind="args" />',
43
+ });
44
+
45
+ export const Primary = Template.bind({});
46
+ Primary.args = {
47
+ type: 'password',
48
+ maxlength: 255,
49
+ id: 'testId',
50
+ name: 'testName',
51
+ placeholder: 'Input placeholder text',
52
+ label: 'Input label text',
53
+ errorMessage: 'This is an error message',
54
+ fieldHasError: false,
55
+ required: true,
56
+ styleClassPassthrough: ['testClass1', 'testClass2'],
57
+ theme: 'primary',
58
+ modelValue: 'This is the model value',
59
+ iconOnly: `<Icon name="radix-icons:eye-none" class="icon" />`,
60
+ };
@@ -10,7 +10,7 @@
10
10
  <slot name="right"></slot>
11
11
  </template>
12
12
  </InputTextareaCore>
13
- <InputError :errorMessage :fieldHasError :id :isDetached="false" />
13
+ <InputError :errorMessage :showError="fieldHasError" :id :isDetached="false" />
14
14
  </div>
15
15
  </template>
16
16
 
package/nuxt.config.ts CHANGED
@@ -1,17 +1,24 @@
1
1
  // https://nuxt.com/docs/api/configuration/nuxt-config
2
- // import { createResolver } from '@nuxt/kit';
3
- // const { resolve } = createResolver(import.meta.url);
4
2
 
5
3
  export default defineNuxtConfig({
6
4
  devtools: { enabled: true },
7
- // css: [resolve('./assets/styles/main.css')],
8
5
  css: ['modern-normalize', './assets/styles/main.css'],
9
- modules: ['@nuxt/icon'],
6
+ modules: ['@nuxt/icon', '@nuxt/test-utils/module', '@nuxtjs/storybook'],
7
+ typescript: {
8
+ tsConfig: {
9
+ compilerOptions: {
10
+ types: ['vitest/globals'], // TypeScript support for globals
11
+ },
12
+ },
13
+ },
10
14
  components: [
11
15
  {
12
16
  path: './components',
13
17
  pathPrefix: false,
14
18
  },
15
19
  ],
20
+ vue: {
21
+ runtimeCompiler: true,
22
+ },
16
23
  compatibilityDate: '2024-07-13',
17
24
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-forms",
3
3
  "type": "module",
4
- "version": "2.1.13",
4
+ "version": "2.1.14",
5
5
  "main": "nuxt.config.ts",
6
6
  "scripts": {
7
7
  "clean": "rm -rf .nuxt && rm -rf .output && rm -rf .playground/.nuxt && rm -rf .playground/.output",
@@ -12,7 +12,9 @@
12
12
  "preview": "nuxt preview .playground",
13
13
  "lint": "eslint .",
14
14
  "postinstall": "nuxt prepare .playground",
15
- "release": "release-it"
15
+ "release": "release-it",
16
+ "storybook": "storybook dev --port 6006 --config-dir .storybook",
17
+ "test": "vitest"
16
18
  },
17
19
  "files": [
18
20
  "assets/",
@@ -23,9 +25,21 @@
23
25
  "devDependencies": {
24
26
  "@nuxt/eslint-config": "0.6.1",
25
27
  "@nuxt/icon": "1.7.5",
28
+ "@nuxt/test-utils": "3.14.4",
29
+ "@nuxtjs/storybook": "8.3.2",
30
+ "@storybook/addon-essentials": "8.4.6",
31
+ "@storybook/addon-interactions": "8.4.6",
32
+ "@storybook/addon-links": "8.4.6",
33
+ "@storybook/vue3": "8.4.6",
34
+ "@vue/test-utils": "2.4.6",
26
35
  "eslint": "9.15.0",
36
+ "happy-dom": "15.11.6",
37
+ "http-proxy-middleware": "3.0.3",
38
+ "nuxt": "3.14.1592",
27
39
  "release-it": "17.10.0",
28
- "typescript": "5.6.3"
40
+ "typescript": "5.6.3",
41
+ "vitest": "2.1.5",
42
+ "vue": "3.5.13"
29
43
  },
30
44
  "dependencies": {
31
45
  "@iconify-json/carbon": "1.2.4",
@@ -34,7 +48,6 @@
34
48
  "@iconify-json/radix-icons": "1.2.1",
35
49
  "@iconify-json/ri": "1.2.3",
36
50
  "modern-normalize": "3.0.1",
37
- "nuxt": "3.14.159",
38
51
  "zod": "3.23.8"
39
52
  },
40
53
  "release-it": {
@@ -1,170 +0,0 @@
1
- <template>
2
- <div class="input-radiobutton-wrapper" :data-form-theme="formTheme" :class="[size, { error: fieldHasError }]">
3
- <slot name="checkedIcon" v-if="isChecked">
4
- <Icon name="material-symbols:circle" class="input-checked-icon" />
5
- </slot>
6
- <input
7
- type="radio"
8
- :true-value="trueValue"
9
- :false-value="falseValue"
10
- :id
11
- :name
12
- :required="required && !multipleOptions"
13
- :value="trueValue"
14
- class="input-radiobutton-core"
15
- :class="[size, { error: fieldHasError }]"
16
- v-model="modelValue"
17
- ref="inputField"
18
- />
19
- </div>
20
- </template>
21
-
22
- <script setup lang="ts">
23
- import propValidators from '../c12/prop-validators';
24
- const { id, name, required, trueValue, falseValue, multipleOptions, theme, styleClassPassthrough, size, fieldHasError } = defineProps({
25
- id: {
26
- type: String,
27
- required: true,
28
- },
29
- name: {
30
- type: String,
31
- required: true,
32
- },
33
- required: {
34
- type: Boolean,
35
- value: false,
36
- },
37
- trueValue: {
38
- type: [String, Number, Boolean],
39
- default: true,
40
- },
41
- falseValue: {
42
- type: [String, Number, Boolean],
43
- default: false,
44
- },
45
- multipleOptions: {
46
- type: Boolean,
47
- default: false,
48
- },
49
- theme: {
50
- type: String as PropType<string>,
51
- default: 'primary',
52
- validator(value: string) {
53
- return propValidators.theme.includes(value);
54
- },
55
- },
56
- size: {
57
- type: String as PropType<string>,
58
- default: 'medium',
59
- validator(value: string) {
60
- return propValidators.size.includes(value);
61
- },
62
- },
63
- fieldHasError: {
64
- type: Boolean,
65
- default: false,
66
- },
67
- styleClassPassthrough: {
68
- type: Array as PropType<string[]>,
69
- default: () => [],
70
- },
71
- });
72
-
73
- const slots = useSlots();
74
- const hasLeftContent = computed(() => slots.left !== undefined);
75
- const hasRightContent = computed(() => slots.right !== undefined);
76
- const { elementClasses, updateElementClasses } = useStyleClassPassthrough(styleClassPassthrough);
77
-
78
- const formTheme = computed(() => {
79
- return fieldHasError ? 'error' : theme;
80
- });
81
-
82
- const modelValue = defineModel<any>();
83
-
84
- const inputField = ref<HTMLInputElement | null>(null);
85
-
86
- const isArray = Array.isArray(modelValue.value);
87
-
88
- const isChecked = computed(() => {
89
- if (isArray) {
90
- return modelValue.value.indexOf(trueValue) > -1;
91
- } else {
92
- return modelValue.value === trueValue;
93
- }
94
- });
95
- </script>
96
-
97
- <style lang="css">
98
- .input-radiobutton-wrapper {
99
- --_checkbox-size: initial;
100
- --_outline-width: var(--input-outline-width-thin);
101
- --_border-width: var(--input-border-width-default);
102
- --_border-color: var(--theme-form-radio-border);
103
- --_outline-color: var(--theme-form-radio-outline);
104
- --_box-shadow: none;
105
-
106
- display: grid;
107
- grid-template-areas: 'element-stack';
108
- /* place-content: center; */
109
-
110
- background-color: var(--theme-form-radio-bg);
111
- border-radius: 50%;
112
- border: var(--_border-width) solid var(--_border-color);
113
- outline: 1px solid var(--_outline-color);
114
- box-shadow: var(--_box-shadow);
115
-
116
- height: var(--_checkbox-size);
117
- width: var(--_checkbox-size);
118
-
119
- &:has(.input-radiobutton-core:focus-visible) {
120
- --_box-shadow: var(--theme-form-focus-box-shadow);
121
- }
122
-
123
- /* Sizes */
124
- &.x-small {
125
- --_checkbox-size: 20px;
126
- }
127
- &.small {
128
- --_checkbox-size: 24px;
129
- }
130
- &.normal {
131
- --_checkbox-size: 34px;
132
- }
133
- &.medium {
134
- --_checkbox-size: 40px;
135
- }
136
- &.large {
137
- --_checkbox-size: 44px;
138
- }
139
-
140
- .input-checked-icon {
141
- --_checked-size: calc(var(--_checkbox-size) * 0.65);
142
- grid-area: element-stack;
143
- align-self: center;
144
- justify-self: center;
145
- color: var(--theme-form-radio-symbol);
146
- height: var(--_checked-size);
147
- width: var(--_checked-size);
148
- translate: -2px -2px;
149
- }
150
-
151
- .input-radiobutton-core {
152
- grid-area: element-stack;
153
- appearance: none;
154
- margin: 0;
155
- overflow: hidden;
156
- opacity: 0;
157
-
158
- height: var(--_checkbox-size);
159
- width: var(--_checkbox-size);
160
-
161
- &:hover {
162
- cursor: pointer;
163
- }
164
-
165
- &:focus-visible {
166
- --_box-shadow: var(--theme-form-focus-box-shadow);
167
- }
168
- }
169
- }
170
- </style>
@@ -1,93 +0,0 @@
1
- <template>
2
- <div class="input-radiobutton-with-label" :class="[elementClasses, { error: fieldHasError }]">
3
- <InputRadiobuttonCore :id :name :required v-model="modelValue" :size :trueValue :falseValue :fieldHasError :theme>
4
- <template #checkedIcon>
5
- <slot name="checkedIcon"></slot>
6
- </template>
7
- </InputRadiobuttonCore>
8
- <label v-if="hasLabelContent" class="input-radiobutton-label body-normal" :for="id">
9
- <slot name="labelContent"></slot>
10
- </label>
11
- <label v-else class="input-radiobutton-label body-normal-semibold" :for="id">{{ label }}</label>
12
- </div>
13
- </template>
14
-
15
- <script setup lang="ts">
16
- import propValidators from '../c12/prop-validators';
17
-
18
- const { id, name, label, required, fieldHasError, trueValue, falseValue, size, styleClassPassthrough, theme } = defineProps({
19
- id: {
20
- type: String,
21
- required: true,
22
- },
23
- name: {
24
- type: String,
25
- required: true,
26
- },
27
- label: {
28
- type: String,
29
- required: true,
30
- },
31
- required: {
32
- type: Boolean,
33
- default: false,
34
- },
35
- fieldHasError: {
36
- type: Boolean,
37
- default: false,
38
- },
39
- trueValue: {
40
- type: [String, Number, Boolean],
41
- default: true,
42
- },
43
- falseValue: {
44
- type: [String, Number, Boolean],
45
- default: false,
46
- },
47
- size: {
48
- type: String as PropType<string>,
49
- default: 'medium',
50
- validator(value: string) {
51
- return propValidators.size.includes(value);
52
- },
53
- },
54
- styleClassPassthrough: {
55
- type: Array as PropType<string[]>,
56
- default: () => [],
57
- },
58
- theme: {
59
- type: String as PropType<string>,
60
- default: 'primary',
61
- validator(value: string) {
62
- return propValidators.theme.includes(value);
63
- },
64
- },
65
- });
66
-
67
- const slots = useSlots();
68
- const hasLabelContent = computed(() => slots.labelContent !== undefined);
69
- const { elementClasses, updateElementClasses } = useStyleClassPassthrough(styleClassPassthrough);
70
-
71
- const modelValue = defineModel();
72
- </script>
73
-
74
- <style lang="css">
75
- .input-radiobutton-with-label {
76
- display: grid;
77
- align-items: center;
78
- grid-template-columns: auto 1fr;
79
-
80
- .input-radiobutton-label {
81
- display: flex;
82
- width: 100%;
83
- height: 100%;
84
- align-items: center;
85
- margin-block: 8px;
86
- padding-inline: 8px;
87
-
88
- &:hover {
89
- cursor: pointer;
90
- }
91
- }
92
- }
93
- </style>