pukaad-ui-lib 1.1.0 → 1.3.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.
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pukaad-ui",
3
3
  "configKey": "pukaadUI",
4
- "version": "1.1.0",
4
+ "version": "1.3.1",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -1,18 +1,48 @@
1
1
  interface InputComboboxProps {
2
2
  name?: string;
3
3
  rules?: object | string | Function;
4
+ label?: string;
5
+ required?: boolean;
6
+ disabledBorder?: boolean;
7
+ showCounter?: boolean;
8
+ limit?: number;
9
+ placeholder?: string;
10
+ options?: InputComboboxOption[];
11
+ multiple?: boolean;
12
+ }
13
+ interface InputComboboxOption {
14
+ label: string;
15
+ value: string;
4
16
  }
5
17
  type __VLS_Props = InputComboboxProps;
6
18
  type __VLS_ModelProps = {
7
- modelValue?: string;
19
+ modelValue?: string | string[];
8
20
  };
9
21
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
10
- declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
- "update:modelValue": (value: string) => any;
22
+ declare var __VLS_18: {}, __VLS_70: {};
23
+ type __VLS_Slots = {} & {
24
+ label?: (props: typeof __VLS_18) => any;
25
+ } & {
26
+ options?: (props: typeof __VLS_70) => any;
27
+ };
28
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
29
+ validate: () => Promise<any>;
30
+ setErrors: (errMsg: string[]) => void;
31
+ fieldRef: import("vue").Ref<any, any>;
32
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
33
+ "update:modelValue": (value: string | string[]) => any;
12
34
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
13
- "onUpdate:modelValue"?: ((value: string) => any) | undefined;
35
+ "onUpdate:modelValue"?: ((value: string | string[]) => any) | undefined;
14
36
  }>, {
15
37
  name: string;
38
+ limit: number;
39
+ multiple: boolean;
16
40
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
17
42
  declare const _default: typeof __VLS_export;
18
43
  export default _default;
44
+ type __VLS_WithSlots<T, S> = T & {
45
+ new (): {
46
+ $slots: S;
47
+ };
48
+ };
@@ -6,20 +6,183 @@
6
6
  v-slot="{ componentField }"
7
7
  v-model="modelValue"
8
8
  >
9
- <ShadFormItem> </ShadFormItem>
9
+ <ShadFormItem>
10
+ <ShadFormLabel v-if="$slots.label || props.label" class="w-full">
11
+ <slot name="label">
12
+ <div
13
+ :class="[
14
+ 'flex-1',
15
+ props.disabledBorder && 'font-body-small-prominent'
16
+ ]"
17
+ >
18
+ {{ props.label }}
19
+ <span v-if="props.required" class="text-destructive">*</span>
20
+ </div>
21
+ </slot>
22
+ <div
23
+ v-if="props.showCounter"
24
+ :class="[props.disabledBorder && 'font-body-small']"
25
+ >
26
+ <div
27
+ v-if="props.limit > 0"
28
+ :class="[
29
+ (props.multiple ? modelValue.length : modelValue.length) > props.limit && 'text-destructive'
30
+ ]"
31
+ >
32
+ {{
33
+ props.multiple ? modelValue.length : modelValue.length
34
+ }}/{{ props.limit }}
35
+ </div>
36
+ </div>
37
+ </ShadFormLabel>
38
+ <ShadPopover v-bind="componentField">
39
+ <ShadPopoverTrigger as-child>
40
+ <ShadFormControl>
41
+ <ShadButton
42
+ variant="outline"
43
+ role="combobox"
44
+ class="w-full justify-between text-start"
45
+ >
46
+ {{ displayValue }}
47
+ <Icon name="lucide:chevrons-up-down" class="h-4 w-4" />
48
+ </ShadButton>
49
+ </ShadFormControl>
50
+ </ShadPopoverTrigger>
51
+ <ShadPopoverContent>
52
+ <ShadCommand>
53
+ <ShadCommandInput />
54
+ <ShadCommandList>
55
+ <ShadCommandGroup>
56
+ <slot name="options">
57
+ <ShadCommandItem
58
+ v-for="option in options"
59
+ :key="option.value"
60
+ :value="option.value"
61
+ :disabled="isOptionDisabled(option.value)"
62
+ :class="[
63
+ isOptionDisabled(option.value) && 'cursor-not-allowed'
64
+ ]"
65
+ @click="() => handleSelect(option.value)"
66
+ >
67
+ <ShadCheckbox
68
+ v-if="props.multiple"
69
+ :model-value="isSelected(option.value)"
70
+ :disabled="isOptionDisabled(option.value)"
71
+ class="mr-2 pointer-events-none"
72
+ />
73
+
74
+ {{ option.label }}
75
+ <Icon
76
+ v-if="!props.multiple && isSelected(option.value)"
77
+ name="lucide:check"
78
+ class="ml-auto h-4 w-4"
79
+ />
80
+ </ShadCommandItem>
81
+ </slot>
82
+ </ShadCommandGroup>
83
+ <ShadCommandEmpty />
84
+ </ShadCommandList>
85
+ </ShadCommand>
86
+ </ShadPopoverContent>
87
+ </ShadPopover>
88
+ <ShadFormMessage />
89
+ </ShadFormItem>
10
90
  </ShadFormField>
11
91
  </template>
12
92
 
13
93
  <script setup>
14
- import { ref } from "vue";
94
+ import { ref, computed, watch, onMounted } from "vue";
15
95
  const props = defineProps({
16
96
  name: { type: String, required: false, default: "input-combobox" },
17
- rules: { type: [Object, String, Function], required: false }
97
+ rules: { type: [Object, String, Function], required: false },
98
+ label: { type: String, required: false },
99
+ required: { type: Boolean, required: false },
100
+ disabledBorder: { type: Boolean, required: false },
101
+ showCounter: { type: Boolean, required: false },
102
+ limit: { type: Number, required: false, default: 0 },
103
+ placeholder: { type: String, required: false },
104
+ options: { type: Array, required: false },
105
+ multiple: { type: Boolean, required: false, default: false }
18
106
  });
19
- const modelValue = defineModel({ type: String, ...{
20
- default: ""
107
+ const modelValue = defineModel({ type: [String, Array], ...{
108
+ default: () => ""
21
109
  } });
110
+ const popoverOpen = ref(false);
22
111
  const fieldRef = ref();
23
112
  const defaultRules = (v) => {
113
+ return true;
114
+ };
115
+ onMounted(() => {
116
+ if (props.multiple && modelValue.value === "") {
117
+ modelValue.value = [];
118
+ }
119
+ });
120
+ const displayValue = computed(() => {
121
+ if (props.multiple) {
122
+ const selectedValues = modelValue.value;
123
+ if (!selectedValues || selectedValues.length === 0) {
124
+ return props.placeholder || "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23";
125
+ }
126
+ const selectedLabels = selectedValues.map((val) => props.options?.find((opt) => opt.value === val)?.label).filter(Boolean);
127
+ return selectedLabels.length > 0 ? selectedLabels.join(", ") : props.placeholder || "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23";
128
+ } else {
129
+ const selectedOption = props.options?.find(
130
+ (opt) => opt.value === modelValue.value
131
+ );
132
+ return selectedOption?.label || props.placeholder || "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23";
133
+ }
134
+ });
135
+ const isLimitReached = computed(() => {
136
+ if (!props.multiple || props.limit <= 0) return false;
137
+ return modelValue.value.length >= props.limit;
138
+ });
139
+ const isSelected = (value) => {
140
+ if (props.multiple) {
141
+ const result = modelValue.value.includes(value);
142
+ return result;
143
+ } else {
144
+ return modelValue.value === value;
145
+ }
24
146
  };
147
+ const isOptionDisabled = (value) => {
148
+ if (isLimitReached.value && !isSelected(value)) {
149
+ return true;
150
+ }
151
+ return false;
152
+ };
153
+ const handleSelect = (value) => {
154
+ if (props.multiple) {
155
+ const currentValues = modelValue.value || [];
156
+ if (currentValues.includes(value)) {
157
+ modelValue.value = currentValues.filter((v) => v !== value);
158
+ } else {
159
+ if (props.limit > 0 && currentValues.length >= props.limit) {
160
+ return;
161
+ }
162
+ modelValue.value = [...currentValues, value];
163
+ }
164
+ } else {
165
+ if (modelValue.value === value) {
166
+ modelValue.value = "";
167
+ } else {
168
+ modelValue.value = value;
169
+ }
170
+ popoverOpen.value = false;
171
+ }
172
+ };
173
+ const validate = async () => {
174
+ if (fieldRef.value) {
175
+ const result = await fieldRef.value.validate();
176
+ return result.valid;
177
+ }
178
+ return true;
179
+ };
180
+ const setErrors = (errMsg) => {
181
+ fieldRef.value?.setErrors(errMsg);
182
+ };
183
+ defineExpose({
184
+ validate,
185
+ setErrors,
186
+ fieldRef
187
+ });
25
188
  </script>
@@ -1,18 +1,48 @@
1
1
  interface InputComboboxProps {
2
2
  name?: string;
3
3
  rules?: object | string | Function;
4
+ label?: string;
5
+ required?: boolean;
6
+ disabledBorder?: boolean;
7
+ showCounter?: boolean;
8
+ limit?: number;
9
+ placeholder?: string;
10
+ options?: InputComboboxOption[];
11
+ multiple?: boolean;
12
+ }
13
+ interface InputComboboxOption {
14
+ label: string;
15
+ value: string;
4
16
  }
5
17
  type __VLS_Props = InputComboboxProps;
6
18
  type __VLS_ModelProps = {
7
- modelValue?: string;
19
+ modelValue?: string | string[];
8
20
  };
9
21
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
10
- declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
- "update:modelValue": (value: string) => any;
22
+ declare var __VLS_18: {}, __VLS_70: {};
23
+ type __VLS_Slots = {} & {
24
+ label?: (props: typeof __VLS_18) => any;
25
+ } & {
26
+ options?: (props: typeof __VLS_70) => any;
27
+ };
28
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
29
+ validate: () => Promise<any>;
30
+ setErrors: (errMsg: string[]) => void;
31
+ fieldRef: import("vue").Ref<any, any>;
32
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
33
+ "update:modelValue": (value: string | string[]) => any;
12
34
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
13
- "onUpdate:modelValue"?: ((value: string) => any) | undefined;
35
+ "onUpdate:modelValue"?: ((value: string | string[]) => any) | undefined;
14
36
  }>, {
15
37
  name: string;
38
+ limit: number;
39
+ multiple: boolean;
16
40
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
17
42
  declare const _default: typeof __VLS_export;
18
43
  export default _default;
44
+ type __VLS_WithSlots<T, S> = T & {
45
+ new (): {
46
+ $slots: S;
47
+ };
48
+ };
@@ -27,8 +27,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
27
27
  label: string;
28
28
  name: string;
29
29
  limit: number;
30
- disabledErrorMessage: boolean;
31
30
  accept: string;
31
+ disabledErrorMessage: boolean;
32
32
  labelIcon: string;
33
33
  disabledDrop: boolean;
34
34
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -27,8 +27,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
27
27
  label: string;
28
28
  name: string;
29
29
  limit: number;
30
- disabledErrorMessage: boolean;
31
30
  accept: string;
31
+ disabledErrorMessage: boolean;
32
32
  labelIcon: string;
33
33
  disabledDrop: boolean;
34
34
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -18,8 +18,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
18
18
  }>, {
19
19
  id: string;
20
20
  name: string;
21
- new: boolean;
22
21
  disabledForgotPassword: boolean;
22
+ new: boolean;
23
23
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
24
24
  declare const _default: typeof __VLS_export;
25
25
  export default _default;
@@ -18,8 +18,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
18
18
  }>, {
19
19
  id: string;
20
20
  name: string;
21
- new: boolean;
22
21
  disabledForgotPassword: boolean;
22
+ new: boolean;
23
23
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
24
24
  declare const _default: typeof __VLS_export;
25
25
  export default _default;
@@ -12,9 +12,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
12
12
  color: InputSliderColor;
13
13
  fullWidth: boolean;
14
14
  label: string;
15
+ step: number;
15
16
  min: number;
16
17
  max: number;
17
- step: number;
18
18
  lineHeight: number | string;
19
19
  appearance: boolean;
20
20
  thumbSize: number | string;
@@ -12,9 +12,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
12
12
  color: InputSliderColor;
13
13
  fullWidth: boolean;
14
14
  label: string;
15
+ step: number;
15
16
  min: number;
16
17
  max: number;
17
- step: number;
18
18
  lineHeight: number | string;
19
19
  appearance: boolean;
20
20
  thumbSize: number | string;
@@ -57,8 +57,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
57
57
  limit: number;
58
58
  disabledErrorMessage: boolean;
59
59
  disabledBorder: boolean;
60
- readonly: boolean;
61
60
  showCounter: boolean;
61
+ readonly: boolean;
62
62
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
63
63
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
64
64
  declare const _default: typeof __VLS_export;
@@ -57,8 +57,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
57
57
  limit: number;
58
58
  disabledErrorMessage: boolean;
59
59
  disabledBorder: boolean;
60
- readonly: boolean;
61
60
  showCounter: boolean;
61
+ readonly: boolean;
62
62
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
63
63
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
64
64
  declare const _default: typeof __VLS_export;
@@ -29,9 +29,9 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
29
29
  rows: number | string;
30
30
  disabledErrorMessage: boolean;
31
31
  disabledBorder: boolean;
32
+ showCounter: boolean;
32
33
  resize: "none" | "both" | "horizontal" | "vertical";
33
34
  readonly: boolean;
34
- showCounter: boolean;
35
35
  standalone: boolean;
36
36
  inputClass: string;
37
37
  disabledBorderFocus: boolean;
@@ -29,9 +29,9 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
29
29
  rows: number | string;
30
30
  disabledErrorMessage: boolean;
31
31
  disabledBorder: boolean;
32
+ showCounter: boolean;
32
33
  resize: "none" | "both" | "horizontal" | "vertical";
33
34
  readonly: boolean;
34
- showCounter: boolean;
35
35
  standalone: boolean;
36
36
  inputClass: string;
37
37
  disabledBorderFocus: boolean;
@@ -20,8 +20,16 @@ const isRender = computed(
20
20
  <Primitive
21
21
  v-if="isRender"
22
22
  data-slot="command-empty"
23
- v-bind="delegatedProps" :class="cn('py-6 text-center text-sm', props.class)"
23
+ v-bind="delegatedProps"
24
+ :class="
25
+ cn(
26
+ 'flex flex-col h-[192px] items-center justify-center gap-[8px] ',
27
+ props.class
28
+ )
29
+ "
24
30
  >
25
31
  <slot />
32
+ <Icon name="pukaad:page-not-found" class="h-[64px] w-[74px]" />
33
+ <div class="text-gray font-body-medium">ไม่พบข้อมูล</div>
26
34
  </Primitive>
27
35
  </template>
@@ -24,7 +24,7 @@ const { filterState } = useCommand();
24
24
  data-slot="command-input-wrapper"
25
25
  class="flex h-9 items-center gap-2 border-b px-3"
26
26
  >
27
- <!-- <MagnifyingGlassIcon class="size-4 shrink-0 opacity-50" /> -->
27
+ <Icon name="lucide:search" class="h-4 w-4" />
28
28
  <ListboxFilter
29
29
  v-bind="{ ...forwardedProps, ...$attrs }"
30
30
  v-model="filterState.search"
@@ -40,16 +40,12 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
40
40
 
41
41
  <template>
42
42
  <PopoverPortal>
43
- <PopoverContent
44
- data-slot="popover-content"
45
- v-bind="{ ...$attrs, ...forwarded }"
46
- :class="
43
+ <PopoverContent data-slot="popover-content" v-bind="{ ...$attrs, ...forwarded }" :class="
47
44
  cn(
48
- 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border p-4 shadow-md origin-(--reka-popover-content-transform-origin) outline-hidden',
45
+ 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 rounded-md border shadow-md origin-(--reka-popover-content-transform-origin) outline-hidden max-h-[312px] overflow-auto w-[var(--reka-popover-trigger-width)]',
49
46
  props.class
50
47
  )
51
- "
52
- >
48
+ ">
53
49
  <slot />
54
50
  </PopoverContent>
55
51
  </PopoverPortal>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pukaad-ui-lib",
3
- "version": "1.1.0",
3
+ "version": "1.3.1",
4
4
  "description": "pukaad-ui for MeMSG",
5
5
  "repository": {
6
6
  "type": "git",