@resee-movies/nuxt-ux 0.5.0 → 0.7.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 (27) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/IconTextPair.vue +1 -1
  3. package/dist/runtime/components/ToggleButton.vue +45 -0
  4. package/dist/runtime/components/ToggleButton.vue.d.ts +30 -0
  5. package/dist/runtime/components/form/Form.vue +41 -8
  6. package/dist/runtime/components/form/Form.vue.d.ts +11 -3
  7. package/dist/runtime/components/form/FormField.vue +11 -8
  8. package/dist/runtime/components/form/FormField.vue.d.ts +5 -1
  9. package/dist/runtime/components/form/FormFieldCheckbox.vue +6 -2
  10. package/dist/runtime/components/form/FormFieldSelect.vue +12 -3
  11. package/dist/runtime/components/form/FormFieldSelect.vue.d.ts +24 -10
  12. package/dist/runtime/components/form/FormFieldSelectButton.vue +75 -0
  13. package/dist/runtime/components/form/FormFieldSelectButton.vue.d.ts +16 -0
  14. package/dist/runtime/components/form/FormFieldText.vue +0 -1
  15. package/dist/runtime/components/form/FormFieldToggleSwitch.vue +0 -1
  16. package/dist/runtime/components/form/FormSubmitButton.vue +7 -20
  17. package/dist/runtime/components/form/FormSubmitButton.vue.d.ts +3 -1
  18. package/dist/runtime/components/form/element/FormElementSelectButton.vue +110 -0
  19. package/dist/runtime/components/form/element/FormElementSelectButton.vue.d.ts +33 -0
  20. package/dist/runtime/components/form/element/FormElementSelectOptions.vue +8 -2
  21. package/dist/runtime/components/form/element/FormElementSelectOptions.vue.d.ts +12 -1
  22. package/dist/runtime/composables/use-reactive-objects-sync.d.ts +18 -0
  23. package/dist/runtime/composables/use-reactive-objects-sync.js +73 -0
  24. package/dist/runtime/composables/use-resee-ux.d.ts +1 -0
  25. package/dist/runtime/composables/use-resee-ux.js +1 -0
  26. package/dist/runtime/theme/css/brand/form.css +3 -1
  27. package/package.json +2 -2
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@resee-movies/nuxt-ux",
3
3
  "configKey": "ux",
4
- "version": "0.5.0",
4
+ "version": "0.7.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.0"
@@ -50,5 +50,5 @@ const slots = useSlots();
50
50
  </script>
51
51
 
52
52
  <style scoped>
53
- @reference "tailwindcss";.pair{--element-spacing:--spacing(1);align-items:baseline;display:inline}.pair.spacing-none{--element-spacing:0}.pair.spacing-wide{--element-spacing:--spacing(2)}.pair :deep(.leading-icon)>*{margin-inline-end:var(--element-spacing)}.pair :deep(.trailing-icon)>*{margin-inline-start:var(--element-spacing)}@variant max-md{.pair:is(.responsive-shrink .pair) :deep(.leading-icon)>*{margin-inline-end:0}.pair:is(.responsive-shrink .pair) :deep(.trailing-icon)>*{margin-inline-start:0}}
53
+ @reference "tailwindcss";.pair{--element-spacing:--spacing(1);align-items:baseline;display:inline}.pair.spacing-none{--element-spacing:0}.pair.spacing-wide{--element-spacing:--spacing(2)}.pair :deep(.leading-icon)>*{margin-inline-end:var(--element-spacing)}.pair :deep(.trailing-icon)>*{margin-inline-start:var(--element-spacing)}@variant max-md{.pair:is(.responsive-shrink .pair):deep(.leading-icon)>*{margin-inline-end:0}.pair:is(.responsive-shrink .pair):deep(.trailing-icon)>*{margin-inline-start:0}}
54
54
  </style>
@@ -0,0 +1,45 @@
1
+ <template>
2
+ <Button
3
+ :text = "currentText"
4
+ :icon = "currentIcon"
5
+ :aria-pressed = "pressed"
6
+ @click = "handleClick"
7
+ >
8
+ <template #default v-if="slots.default">
9
+ <slot />
10
+ </template>
11
+ </Button>
12
+ </template>
13
+
14
+ <script>
15
+
16
+ </script>
17
+
18
+ <script setup>
19
+ import { computed, useSlots, watch } from "vue";
20
+ import Button from "./Button.vue";
21
+ const props = defineProps({
22
+ onIcon: { type: String, required: false, default: void 0 },
23
+ offIcon: { type: String, required: false, default: void 0 },
24
+ onText: { type: String, required: false, default: void 0 },
25
+ offText: { type: String, required: false, default: void 0 }
26
+ });
27
+ const emits = defineEmits(["click", "change"]);
28
+ const pressed = defineModel("pressed", { type: Boolean, ...{ default: false } });
29
+ const slots = useSlots();
30
+ const currentText = computed(() => {
31
+ return pressed.value ? props.onText ?? props.text : props.offText ?? props.text;
32
+ });
33
+ const currentIcon = computed(() => {
34
+ return pressed.value ? props.onIcon ?? props.icon : props.offIcon ?? props.icon;
35
+ });
36
+ watch(pressed, (newVal, oldVal) => {
37
+ if (newVal !== oldVal) {
38
+ emits("change", newVal);
39
+ }
40
+ });
41
+ function handleClick() {
42
+ pressed.value = !pressed.value;
43
+ emits("click", pressed.value);
44
+ }
45
+ </script>
@@ -0,0 +1,30 @@
1
+ import type { ButtonProps } from './Button.vue.js';
2
+ export interface ToggleButtonProps extends /* @vue-ignore */ Omit<ButtonProps, 'onClick' | 'trailingIcon' | 'trailingIconSize'> {
3
+ onIcon?: string;
4
+ offIcon?: string;
5
+ onText?: string;
6
+ offText?: string;
7
+ }
8
+ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<ToggleButtonProps & {
9
+ pressed?: boolean;
10
+ }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
+ "update:pressed": (value: boolean) => any;
12
+ } & {
13
+ change: (pressed: boolean) => any;
14
+ click: (pressed: boolean) => any;
15
+ }, string, import("vue").PublicProps, Readonly<ToggleButtonProps & {
16
+ pressed?: boolean;
17
+ }> & Readonly<{
18
+ onChange?: ((pressed: boolean) => any) | undefined;
19
+ onClick?: ((pressed: boolean) => any) | undefined;
20
+ "onUpdate:pressed"?: ((value: boolean) => any) | undefined;
21
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
22
+ default?: (props: {}) => any;
23
+ }>;
24
+ declare const _default: typeof __VLS_export;
25
+ export default _default;
26
+ type __VLS_WithSlots<T, S> = T & {
27
+ new (): {
28
+ $slots: S;
29
+ };
30
+ };
@@ -1,12 +1,13 @@
1
1
  <template>
2
2
  <PrimeForm
3
3
  v-slot = "$form"
4
+ ref = "form"
4
5
  novalidate = "true"
5
6
  :validate-on-mount = "true"
6
7
  :validate-on-submit = "true"
7
8
  :validate-on-value-update = "true"
8
9
  :validate-on-blur = "false"
9
- :initial-values = "props.initialValues"
10
+ :initial-values = "values"
10
11
  :aria-disabled = "props.disabled"
11
12
  @submit = "handleFormSubmit"
12
13
  >
@@ -19,28 +20,60 @@ export * from "../../types/form";
19
20
  </script>
20
21
 
21
22
  <script setup>
22
- import PrimeForm from "@primevue/forms/form";
23
+ import PrimeForm, {} from "@primevue/forms/form";
23
24
  import { toNonNullableArray } from "@resee-movies/utilities/arrays/to-non-nullable-array";
24
25
  import { isPromiseLike } from "@resee-movies/utilities/objects/is-promise-like";
25
- import { syncRefs } from "@vueuse/core";
26
+ import { syncRefs, useDebounceFn } from "@vueuse/core";
27
+ import { useTemplateRef } from "vue";
28
+ import { useReactiveObjectsSync } from "../../composables/use-reactive-objects-sync";
26
29
  import { provideFormInstance, getValuesFromFormState } from "../../utils/form";
27
30
  const props = defineProps({
28
31
  disabled: { type: Boolean, required: false },
29
- initialValues: { type: Object, required: false },
30
- onSubmit: { type: [Function, Array], required: false }
32
+ onSubmit: { type: [Function, Array], required: false },
33
+ onChange: { type: Function, required: false }
31
34
  });
32
- defineEmits(["submit"]);
35
+ const form = useTemplateRef("form");
36
+ const values = defineModel("values", { type: null, ...{ default: void 0 } });
37
+ defineEmits(["submit", "change"]);
33
38
  const formInstance = provideFormInstance();
34
39
  syncRefs(() => props.disabled, formInstance.isDisabled);
40
+ const emitOnChange = useDebounceFn(() => {
41
+ const state = form.value?.states;
42
+ if (state) {
43
+ props.onChange?.(getValuesFromFormState(state));
44
+ }
45
+ }, 1);
46
+ useReactiveObjectsSync({
47
+ left: () => form.value?.states,
48
+ right: () => values.value,
49
+ keySource: "left",
50
+ leftOptions: {
51
+ onChange: () => emitOnChange(),
52
+ getter(obj, key) {
53
+ return obj[key]?.value;
54
+ },
55
+ setter(obj, key, val) {
56
+ if (obj[key]) {
57
+ obj[key].value = val ?? null;
58
+ }
59
+ }
60
+ },
61
+ rightOptions: {
62
+ onChange: () => emitOnChange()
63
+ }
64
+ });
35
65
  async function handleFormSubmit(event) {
66
+ if (props.disabled) {
67
+ return;
68
+ }
36
69
  formInstance.hasSubmitted.value = true;
37
70
  if (!event.valid) {
38
71
  return;
39
72
  }
40
73
  if (props.onSubmit) {
41
74
  const handlers = toNonNullableArray(props.onSubmit);
42
- const values = getValuesFromFormState(event.states);
43
- const newEvent = { ...event, values };
75
+ const values2 = getValuesFromFormState(event.states);
76
+ const newEvent = { ...event, values: values2 };
44
77
  const results = handlers.map((handler) => handler(newEvent));
45
78
  if (!!results.find((result) => isPromiseLike(result))) {
46
79
  formInstance.isSubmitting.value = true;
@@ -2,11 +2,16 @@ import type { FormValues, FormSubmitHandler, FormSubmitEvent } from '../../types
2
2
  export * from '../../types/form.js';
3
3
  export interface FormProps<T extends FormValues = FormValues> {
4
4
  disabled?: boolean;
5
- initialValues?: Record<string, unknown>;
6
5
  onSubmit?: FormSubmitHandler<T> | FormSubmitHandler<T>[];
6
+ onChange?: (values: T | null) => void;
7
7
  }
8
8
  declare const __VLS_export: <T extends FormValues>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
9
- props: __VLS_PrettifyLocal<FormProps<T> & __VLS_EmitsToProps<__VLS_NormalizeEmits<(e: "submit", evt: FormSubmitEvent<T>) => (void | Promise<void>)>>> & import("vue").PublicProps & (typeof globalThis extends {
9
+ props: __VLS_PrettifyLocal<(FormProps<T> & {
10
+ values?: Partial<T> | undefined;
11
+ }) & __VLS_EmitsToProps<__VLS_NormalizeEmits<{
12
+ (e: "submit", evt: FormSubmitEvent<T>): (void | Promise<void>);
13
+ (e: "change", values: T): void;
14
+ } & ((evt: "update:values", value: Partial<T> | undefined) => void)>>> & import("vue").PublicProps & (typeof globalThis extends {
10
15
  __VLS_PROPS_FALLBACK: infer P;
11
16
  } ? P : {});
12
17
  expose: (exposed: {}) => void;
@@ -16,7 +21,10 @@ declare const __VLS_export: <T extends FormValues>(__VLS_props: NonNullable<Awai
16
21
  state: any;
17
22
  }) => any;
18
23
  };
19
- emit: (e: "submit", evt: FormSubmitEvent<T>) => (void | Promise<void>);
24
+ emit: {
25
+ (e: "submit", evt: FormSubmitEvent<T>): (void | Promise<void>);
26
+ (e: "change", values: T): void;
27
+ } & ((evt: "update:values", value: Partial<T> | undefined) => void);
20
28
  }>) => import("vue").VNode & {
21
29
  __ctx?: Awaited<typeof __VLS_setup>;
22
30
  };
@@ -1,11 +1,10 @@
1
1
  <template>
2
2
  <PrimeFormField
3
- v-slot = "$field"
4
- :as = "props.is"
5
- :name = "props.name"
6
- :resolver = "validatorFunction"
7
- :initial-value = "props.initialValue"
8
- :class = "['input-field', props.class, { disabled: isDisabled, readonly: isReadonly, required: props.required }]"
3
+ v-slot = "$field"
4
+ :as = "props.is"
5
+ :name = "props.name"
6
+ :resolver = "validatorFunction"
7
+ :class = "['input-field', props.class, { disabled: isDisabled, readonly: isReadonly, required: props.required }]"
9
8
  >
10
9
  <FormLabelInputPair
11
10
  :input-id = "inputId"
@@ -13,7 +12,7 @@
13
12
  :label-text = "labelText"
14
13
  :label-position = "props.labelPosition"
15
14
  :label-sr-only = "props.labelSrOnly"
16
- :disabled = "props.disabled"
15
+ :disabled = "isDisabled && !isReadonly"
17
16
  :required = "props.required"
18
17
  :faux-label = "props.fauxLabel"
19
18
  >
@@ -31,6 +30,11 @@
31
30
  :message-id = "$field.error ? messageId : void 0"
32
31
  :disabled = "isDisabled"
33
32
  :readonly = "isReadonly"
33
+ :invalid = "$field.invalid"
34
+ :on-blur = "$field.props.onBlur"
35
+ :on-change = "$field.props.onChange"
36
+ :on-input = "$field.props.onInput"
37
+ :on-invalid = "$field.props.onInvalid"
34
38
  />
35
39
  </template>
36
40
  </FormLabelInputPair>
@@ -62,7 +66,6 @@ const props = defineProps({
62
66
  name: { type: String, required: true },
63
67
  label: { type: String, required: false, default: void 0 },
64
68
  is: { type: String, required: false, default: "div" },
65
- initialValue: { type: null, required: false, default: void 0 },
66
69
  required: { type: Boolean, required: false, default: false },
67
70
  disabled: { type: Boolean, required: false, default: false },
68
71
  readonly: { type: Boolean, required: false, default: false },
@@ -5,7 +5,6 @@ export interface FormFieldProps {
5
5
  name: string;
6
6
  label?: string;
7
7
  is?: HintedString<'div'>;
8
- initialValue?: unknown;
9
8
  required?: boolean;
10
9
  disabled?: boolean;
11
10
  readonly?: boolean;
@@ -26,6 +25,11 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<FormFi
26
25
  messageId: any;
27
26
  disabled: any;
28
27
  readonly: any;
28
+ invalid: any;
29
+ onBlur: any;
30
+ onChange: any;
31
+ onInput: any;
32
+ onInvalid: any;
29
33
  }) => any;
30
34
  }>;
31
35
  declare const _default: typeof __VLS_export;
@@ -15,7 +15,11 @@
15
15
  :disabled = "disabled || readonly"
16
16
  :readonly = "readonly"
17
17
  class = "input-group"
18
- />
18
+ >
19
+ <template #icon="{ checked }">
20
+ <Icon v-if="checked" name="i-ph-check-bold" />
21
+ </template>
22
+ </PrimeCheckbox>
19
23
  </template>
20
24
  </FormField>
21
25
  </template>
@@ -28,6 +32,7 @@ import { computed } from "vue";
28
32
  import PrimeCheckbox from "primevue/checkbox";
29
33
  import { createBooleanValidator } from "../../utils/validation";
30
34
  import FormField from "./FormField.vue";
35
+ import Icon from "../Icon.vue";
31
36
  const props = defineProps({
32
37
  value: { type: null, required: false, default: void 0 },
33
38
  trueValue: { type: null, required: false, default: () => true },
@@ -36,7 +41,6 @@ const props = defineProps({
36
41
  name: { type: String, required: true },
37
42
  label: { type: String, required: false },
38
43
  is: { type: String, required: false },
39
- initialValue: { type: null, required: false, default: () => false },
40
44
  required: { type: Boolean, required: false },
41
45
  disabled: { type: Boolean, required: false },
42
46
  readonly: { type: Boolean, required: false },
@@ -24,7 +24,16 @@
24
24
  :filter-placeholder = "props.filterPlaceholder"
25
25
  :loading = "props.loading"
26
26
  :selection-limit = "props.maxRequired"
27
- />
27
+ >
28
+ <template #option="{ option, selected, index }" v-if="slots.option">
29
+ <slot
30
+ name = "option"
31
+ :option = "option"
32
+ :selected = "selected"
33
+ :index = "index"
34
+ />
35
+ </template>
36
+ </FormElementSelectOptions>
28
37
  </template>
29
38
  </FormField>
30
39
  </template>
@@ -34,7 +43,7 @@ import {} from "./FormField.vue";
34
43
  </script>
35
44
 
36
45
  <script setup>
37
- import { computed } from "vue";
46
+ import { computed, useSlots } from "vue";
38
47
  import { createBooleanValidator, createListValidator } from "../../utils/validation";
39
48
  import FormField from "./FormField.vue";
40
49
  import FormElementSelectOptions from "./element/FormElementSelectOptions.vue";
@@ -55,7 +64,6 @@ const props = defineProps({
55
64
  name: { type: String, required: true },
56
65
  label: { type: String, required: false },
57
66
  is: { type: String, required: false },
58
- initialValue: { type: null, required: false },
59
67
  required: { type: Boolean, required: false },
60
68
  disabled: { type: Boolean, required: false },
61
69
  readonly: { type: Boolean, required: false },
@@ -64,6 +72,7 @@ const props = defineProps({
64
72
  labelPosition: { type: String, required: false },
65
73
  class: { type: null, required: false }
66
74
  });
75
+ const slots = useSlots();
67
76
  const validatorFunction = computed(() => {
68
77
  return props.multiple ? () => createListValidator({
69
78
  required: props.required,
@@ -1,6 +1,6 @@
1
1
  import { type FormFieldProps } from './FormField.vue.js';
2
- export interface FormFieldSelectProps extends Omit<FormFieldProps, 'validator'> {
3
- options?: unknown[];
2
+ export interface FormFieldSelectProps<T = unknown> extends Omit<FormFieldProps, 'validator'> {
3
+ options?: T[];
4
4
  optionLabel?: string;
5
5
  optionValue?: string;
6
6
  optionDisabled?: string;
@@ -14,13 +14,27 @@ export interface FormFieldSelectProps extends Omit<FormFieldProps, 'validator'>
14
14
  minRequired?: string | number;
15
15
  maxRequired?: string | number;
16
16
  }
17
- declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<FormFieldSelectProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FormFieldSelectProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
18
- label?: (props: {}) => any;
19
- }>;
20
- declare const _default: typeof __VLS_export;
21
- export default _default;
22
- type __VLS_WithSlots<T, S> = T & {
23
- new (): {
24
- $slots: S;
17
+ declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
18
+ props: __VLS_PrettifyLocal<FormFieldSelectProps<T>> & import("vue").PublicProps & (typeof globalThis extends {
19
+ __VLS_PROPS_FALLBACK: infer P;
20
+ } ? P : {});
21
+ expose: (exposed: {}) => void;
22
+ attrs: any;
23
+ slots: {
24
+ label?: (props: {}) => any;
25
+ } & {
26
+ option?: (props: {
27
+ option: T;
28
+ selected: any;
29
+ index: any;
30
+ }) => any;
25
31
  };
32
+ emit: {};
33
+ }>) => import("vue").VNode & {
34
+ __ctx?: Awaited<typeof __VLS_setup>;
26
35
  };
36
+ declare const _default: typeof __VLS_export;
37
+ export default _default;
38
+ type __VLS_PrettifyLocal<T> = {
39
+ [K in keyof T as K]: T[K];
40
+ } & {};
@@ -0,0 +1,75 @@
1
+ <template>
2
+ <FormField v-bind="props" :validator="validatorFunction">
3
+ <template #label>
4
+ <slot name="label" />
5
+ </template>
6
+
7
+ <template #default="{ labelId, messageId, invalid, disabled, readonly, onChange, onBlur }">
8
+ <FormElementSelectButton
9
+ :aria-labelledby = "labelId"
10
+ :aria-describedby = "messageId"
11
+ :aria-invalid = "invalid"
12
+ :disabled = "disabled"
13
+ :readonly = "readonly"
14
+ :options = "props.options"
15
+ :option-label = "props.optionLabel"
16
+ :option-icon = "props.optionIcon"
17
+ :option-value = "props.optionValue"
18
+ :option-disabled = "props.optionDisabled"
19
+ :option-data-key = "props.optionDataKey"
20
+ :icon-only = "props.iconOnly"
21
+ :multiple = "props.multiple"
22
+ :selection-limit = "props.maxRequired ? toInteger(props.maxRequired) : void 0"
23
+ @change = "onChange"
24
+ @focusout = "onBlur"
25
+ />
26
+ </template>
27
+ </FormField>
28
+ </template>
29
+
30
+ <script>
31
+ import {} from "./element/FormElementSelectButton.vue";
32
+ import {} from "./FormField.vue";
33
+ </script>
34
+
35
+ <script setup>
36
+ import { toInteger } from "@resee-movies/utilities/numbers/to-integer";
37
+ import { computed } from "vue";
38
+ import { createBooleanValidator, createListValidator } from "../../utils/validation";
39
+ import FormField from "./FormField.vue";
40
+ import FormElementSelectButton from "./element/FormElementSelectButton.vue";
41
+ const props = defineProps({
42
+ minRequired: { type: [String, Number], required: false },
43
+ maxRequired: { type: [String, Number], required: false },
44
+ name: { type: String, required: true },
45
+ label: { type: String, required: false },
46
+ is: { type: String, required: false },
47
+ required: { type: Boolean, required: false },
48
+ disabled: { type: Boolean, required: false },
49
+ readonly: { type: Boolean, required: false },
50
+ fauxLabel: { type: Boolean, required: false, default: true },
51
+ labelSrOnly: { type: Boolean, required: false },
52
+ labelPosition: { type: String, required: false },
53
+ class: { type: null, required: false },
54
+ options: { type: Array, required: true },
55
+ optionLabel: { type: String, required: false },
56
+ optionIcon: { type: String, required: false },
57
+ optionValue: { type: String, required: false },
58
+ optionDisabled: { type: String, required: false },
59
+ optionDataKey: { type: String, required: false },
60
+ iconOnly: { type: Boolean, required: false, default: false },
61
+ multiple: { type: Boolean, required: false, default: false },
62
+ ariaLabelledby: { type: String, required: false },
63
+ ariaDescribedby: { type: String, required: false },
64
+ selectionLimit: { type: Number, required: false }
65
+ });
66
+ const validatorFunction = computed(() => {
67
+ return props.multiple ? () => createListValidator({
68
+ required: props.required,
69
+ minRequired: props.minRequired,
70
+ maxRequired: props.maxRequired
71
+ }) : () => createBooleanValidator({
72
+ required: props.required
73
+ });
74
+ });
75
+ </script>
@@ -0,0 +1,16 @@
1
+ import { type FormElementSelectButtonProps } from './element/FormElementSelectButton.vue.js';
2
+ import { type FormFieldProps } from './FormField.vue.js';
3
+ export interface FormFieldSelectButtonProps extends Omit<FormFieldProps, 'validator'>, FormElementSelectButtonProps {
4
+ minRequired?: string | number;
5
+ maxRequired?: string | number;
6
+ }
7
+ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<FormFieldSelectButtonProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FormFieldSelectButtonProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
8
+ label?: (props: {}) => any;
9
+ }>;
10
+ declare const _default: typeof __VLS_export;
11
+ export default _default;
12
+ type __VLS_WithSlots<T, S> = T & {
13
+ new (): {
14
+ $slots: S;
15
+ };
16
+ };
@@ -36,7 +36,6 @@ const props = defineProps({
36
36
  name: { type: String, required: true },
37
37
  label: { type: String, required: false },
38
38
  is: { type: String, required: false },
39
- initialValue: { type: null, required: false },
40
39
  required: { type: Boolean, required: false },
41
40
  disabled: { type: Boolean, required: false },
42
41
  readonly: { type: Boolean, required: false },
@@ -32,7 +32,6 @@ const props = defineProps({
32
32
  name: { type: String, required: true },
33
33
  label: { type: String, required: false },
34
34
  is: { type: String, required: false },
35
- initialValue: { type: null, required: false, default: () => false },
36
35
  required: { type: Boolean, required: false },
37
36
  disabled: { type: Boolean, required: false },
38
37
  readonly: { type: Boolean, required: false },
@@ -1,8 +1,10 @@
1
1
  <template>
2
2
  <Button
3
- v-bind = "props"
4
3
  type = "submit"
4
+ :text = "props.text ?? locale.form.submitButtonLabel"
5
5
  :loading = "formState.isSubmitting.value"
6
+ :disabled = "formState.isDisabled.value"
7
+ :bordered = "props.bordered"
6
8
  icon-transition-name = "grow-x"
7
9
  />
8
10
  </template>
@@ -12,28 +14,13 @@
12
14
  </script>
13
15
 
14
16
  <script setup>
17
+ import { useReseeUx } from "../../composables/use-resee-ux";
15
18
  import { injectFormInstance } from "../../utils/form";
16
19
  import Button from "../Button.vue";
17
20
  const props = defineProps({
18
- is: { type: null, required: false },
19
- severity: { type: String, required: false },
20
- bordered: { type: Boolean, required: false, default: true },
21
- responsive: { type: [Boolean, String], required: false },
22
- variant: { type: String, required: false },
23
- size: { type: String, required: false },
24
- disabled: { type: Boolean, required: false },
25
- tooltip: { type: String, required: false },
26
- disabledTooltip: { type: String, required: false },
27
- type: { type: String, required: false },
28
- text: { type: String, required: false, default: "Submit" },
29
- icon: { type: String, required: false },
30
- trailingIcon: { type: String, required: false },
31
- iconSize: { type: String, required: false },
32
- trailingIconSize: { type: String, required: false },
33
- spacing: { type: String, required: false },
34
- iconTransitionName: { type: String, required: false },
35
- iconTransitionMode: { type: String, required: false },
36
- iconTransitionOnAppear: { type: Boolean, required: false }
21
+ text: { type: String, required: false, default: void 0 },
22
+ bordered: { type: Boolean, required: false, default: true }
37
23
  });
38
24
  const formState = injectFormInstance();
25
+ const { locale } = useReseeUx();
39
26
  </script>
@@ -1,5 +1,7 @@
1
1
  import type { ButtonProps } from '../Button.vue.js';
2
- export interface FormSubmitButtonProps extends Omit<ButtonProps, 'onClick' | 'loading'> {
2
+ export interface FormSubmitButtonProps extends /* @vue-ignore */ Omit<ButtonProps, 'onClick' | 'loading'> {
3
+ text?: string;
4
+ bordered?: boolean;
3
5
  }
4
6
  declare const __VLS_export: import("vue").DefineComponent<FormSubmitButtonProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FormSubmitButtonProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
5
7
  declare const _default: typeof __VLS_export;
@@ -0,0 +1,110 @@
1
+ <template>
2
+ <div
3
+ role = "group"
4
+ class = "input-group input-button-bar"
5
+ :aria-labelledby = "props.ariaLabelledby"
6
+ :aria-describedby = "props.ariaDescribedby"
7
+ >
8
+ <template v-for="(option, index) of props.options" :key="getOptionRenderKey(option) ?? index">
9
+ <ToggleButton
10
+ severity = "unset"
11
+ :pressed = "getSelectedOptionIndex(option) !== -1"
12
+ :text = "props.iconOnly ? void 0 : getOptionLabel(option)"
13
+ :icon = "getOptionIcon(option)"
14
+ :disabled = "getOptionDisabled(option)"
15
+ :aria-label = "props.iconOnly ? getOptionLabel(option) : void 0"
16
+ :tooltip = "props.iconOnly ? getOptionLabel(option) : void 0"
17
+ @click = "(pressed) => handleToggleChange(option, pressed)"
18
+ />
19
+ </template>
20
+ </div>
21
+ </template>
22
+
23
+ <script>
24
+ export class ChangeEvent extends Event {
25
+ value;
26
+ constructor(value) {
27
+ super("change");
28
+ this.value = value;
29
+ }
30
+ }
31
+ </script>
32
+
33
+ <script setup>
34
+ import { equals, resolveFieldData } from "@primeuix/utils/object";
35
+ import { isNumber } from "@resee-movies/utilities/numbers/is-number";
36
+ import { isString } from "@resee-movies/utilities/strings/is-string";
37
+ import ToggleButton from "../../ToggleButton.vue";
38
+ const props = defineProps({
39
+ options: { type: Array, required: true },
40
+ optionLabel: { type: String, required: false },
41
+ optionIcon: { type: String, required: false },
42
+ optionValue: { type: String, required: false },
43
+ optionDisabled: { type: String, required: false },
44
+ optionDataKey: { type: String, required: false },
45
+ iconOnly: { type: Boolean, required: false, default: false },
46
+ multiple: { type: Boolean, required: false, default: false },
47
+ ariaLabelledby: { type: String, required: false },
48
+ ariaDescribedby: { type: String, required: false },
49
+ disabled: { type: Boolean, required: false, default: false },
50
+ readonly: { type: Boolean, required: false, default: false },
51
+ selectionLimit: { type: Number, required: false }
52
+ });
53
+ const emits = defineEmits(["change"]);
54
+ const value = defineModel("value", { type: null, ...{ default: null } });
55
+ function getOptionLabel(option) {
56
+ return String(props.optionLabel ? resolveFieldData(option, props.optionLabel) : option);
57
+ }
58
+ function getOptionValue(option) {
59
+ return props.optionValue ? resolveFieldData(option, props.optionValue) : option;
60
+ }
61
+ function getOptionIcon(option) {
62
+ return props.optionIcon ? String(resolveFieldData(option, props.optionIcon)) : void 0;
63
+ }
64
+ function getOptionDisabled(option) {
65
+ if (props.disabled || props.readonly) {
66
+ return true;
67
+ }
68
+ if (props.optionDisabled && resolveFieldData(option, props.optionDisabled)) {
69
+ return true;
70
+ }
71
+ if (props.multiple) {
72
+ const limit = props.selectionLimit ?? Number.POSITIVE_INFINITY;
73
+ const length = Array.isArray(value.value) ? value.value.length : 0;
74
+ if (limit <= length && getSelectedOptionIndex(option) === -1) {
75
+ return true;
76
+ }
77
+ }
78
+ return false;
79
+ }
80
+ function getOptionRenderKey(option) {
81
+ const result = props.optionDataKey ? resolveFieldData(option, props.optionDataKey) : getOptionLabel(option);
82
+ return isString(result) || isNumber(result) ? result : void 0;
83
+ }
84
+ function getSelectedOptionIndex(option) {
85
+ if (!value.value) {
86
+ return -1;
87
+ }
88
+ const equalityKey = props.optionValue ? void 0 : props.optionDataKey;
89
+ const optionValue = getOptionValue(option);
90
+ if (Array.isArray(value.value)) {
91
+ return value.value.findIndex((entry) => equals(entry, optionValue, equalityKey));
92
+ }
93
+ return equals(value.value, optionValue, equalityKey) ? 0 : -1;
94
+ }
95
+ function handleToggleChange(option, pressed) {
96
+ if (props.multiple) {
97
+ const selectedIndex = getSelectedOptionIndex(option);
98
+ const selectedItems = Array.isArray(value.value) ? [...value.value] : [];
99
+ if (selectedIndex === -1) {
100
+ selectedItems.push(getOptionValue(option));
101
+ } else {
102
+ selectedItems.splice(selectedIndex, 1);
103
+ }
104
+ value.value = selectedItems.length === 0 ? null : selectedItems;
105
+ } else {
106
+ value.value = pressed ? getOptionValue(option) : null;
107
+ }
108
+ emits("change", new ChangeEvent(value.value));
109
+ }
110
+ </script>
@@ -0,0 +1,33 @@
1
+ export interface FormElementSelectButtonProps {
2
+ options: unknown[];
3
+ optionLabel?: string;
4
+ optionIcon?: string;
5
+ optionValue?: string;
6
+ optionDisabled?: string;
7
+ optionDataKey?: string;
8
+ iconOnly?: boolean;
9
+ multiple?: boolean;
10
+ ariaLabelledby?: string;
11
+ ariaDescribedby?: string;
12
+ disabled?: boolean;
13
+ readonly?: boolean;
14
+ selectionLimit?: number;
15
+ }
16
+ export declare class ChangeEvent extends Event {
17
+ readonly value: unknown;
18
+ constructor(value: unknown);
19
+ }
20
+ declare const __VLS_export: import("vue").DefineComponent<FormElementSelectButtonProps & {
21
+ value?: unknown | unknown[];
22
+ }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
23
+ "update:value": (value: unknown) => any;
24
+ } & {
25
+ change: (event: ChangeEvent) => any;
26
+ }, string, import("vue").PublicProps, Readonly<FormElementSelectButtonProps & {
27
+ value?: unknown | unknown[];
28
+ }> & Readonly<{
29
+ onChange?: ((event: ChangeEvent) => any) | undefined;
30
+ "onUpdate:value"?: ((value: unknown) => any) | undefined;
31
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
32
+ declare const _default: typeof __VLS_export;
33
+ export default _default;
@@ -18,6 +18,7 @@
18
18
  :loading = "props.loading"
19
19
  :pt = "props.multiple ? multiSelectPassthroughProps : selectPassthroughProps"
20
20
  :append-to = "TeleportId"
21
+ checkbox-icon = "i-ph-check-bold"
21
22
  >
22
23
  <template #value="{ value, placeholder }">
23
24
  <template v-if="value">
@@ -61,6 +62,10 @@
61
62
  <template #empty>
62
63
  <span>{{ locale.form.noOptionsAvailable }}</span>
63
64
  </template>
65
+
66
+ <template #option="{ option, selected, index }" v-if="slots.option">
67
+ <slot name="option" :option="option" :selected="selected" :index="index" />
68
+ </template>
64
69
  </Component>
65
70
  </template>
66
71
 
@@ -73,10 +78,10 @@ import { equals, resolveFieldData } from "@primeuix/utils/object";
73
78
  import { useBreakpoints, breakpointsTailwind } from "@vueuse/core";
74
79
  import PrimeMultiSelect from "primevue/multiselect";
75
80
  import PrimeSelect from "primevue/select";
76
- import { computed } from "vue";
81
+ import { computed, useSlots } from "vue";
77
82
  import { useReseeUx } from "../../../composables/use-resee-ux";
78
83
  import { TeleportId } from "../../../constants";
79
- import { blockBodyScroll, unblockBodyScroll } from "../../../utils/dom";
84
+ import { blockBodyScroll } from "../../../utils/dom";
80
85
  import { swapStringPlaceholders } from "../../../utils/string";
81
86
  import Button from "../../Button.vue";
82
87
  import Icon from "../../Icon.vue";
@@ -148,6 +153,7 @@ const props = defineProps({
148
153
  ptOptions: { type: Object, required: false },
149
154
  unstyled: { type: Boolean, required: false }
150
155
  });
156
+ const slots = useSlots();
151
157
  const { locale } = useReseeUx();
152
158
  const isSmall = useBreakpoints(breakpointsTailwind).smallerOrEqual("sm");
153
159
  const showFilter = computed(() => {
@@ -8,6 +8,17 @@ export interface FormElementSelectOptionsProps extends Omit<PrimeSelectProps, 'i
8
8
  ariaDescribedby?: string;
9
9
  selectionLimit?: string | number;
10
10
  }
11
- declare const __VLS_export: import("vue").DefineComponent<FormElementSelectOptionsProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FormElementSelectOptionsProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
11
+ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<FormElementSelectOptionsProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FormElementSelectOptionsProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
12
+ option?: (props: {
13
+ option: any;
14
+ selected: any;
15
+ index: any;
16
+ }) => any;
17
+ }>;
12
18
  declare const _default: typeof __VLS_export;
13
19
  export default _default;
20
+ type __VLS_WithSlots<T, S> = T & {
21
+ new (): {
22
+ $slots: S;
23
+ };
24
+ };
@@ -0,0 +1,18 @@
1
+ import { type MaybeRefOrGetter } from 'vue';
2
+ export type SyncObject = Record<string | number | symbol, unknown>;
3
+ export type KeyOf<S extends SyncObject> = keyof S;
4
+ export type Getter<S extends SyncObject> = <R>(obj: S, key: KeyOf<S>) => R;
5
+ export type Setter<S extends SyncObject> = (obj: S, key: KeyOf<S>, value: unknown) => void;
6
+ export type ComputedReadWriteOptions<S extends SyncObject> = {
7
+ getter?: Getter<S>;
8
+ setter?: Setter<S>;
9
+ onChange?: (key: KeyOf<S>, value: unknown) => void;
10
+ };
11
+ export type UseReactiveObjectsSyncOptions<L extends SyncObject, R extends SyncObject> = {
12
+ left: MaybeRefOrGetter<L | undefined>;
13
+ right: MaybeRefOrGetter<R | undefined>;
14
+ keySource?: 'left' | 'right' | (KeyOf<L> | KeyOf<R>)[];
15
+ leftOptions?: ComputedReadWriteOptions<L>;
16
+ rightOptions?: ComputedReadWriteOptions<R>;
17
+ };
18
+ export declare function useReactiveObjectsSync<L extends SyncObject, R extends SyncObject>(options: UseReactiveObjectsSyncOptions<L, R>): void;
@@ -0,0 +1,73 @@
1
+ import { syncRef } from "@vueuse/core";
2
+ import {
3
+ toValue,
4
+ watchEffect,
5
+ watch,
6
+ computed,
7
+ shallowRef
8
+ } from "vue";
9
+ export function useReactiveObjectsSync(options) {
10
+ const { left, right } = options;
11
+ const watchKeys = aggregateKeys(options);
12
+ const syncHandle = /* @__PURE__ */ new Map();
13
+ watch(watchKeys, (newKeys, oldKeys) => {
14
+ for (const key of oldKeys.difference(newKeys)) {
15
+ const handle = syncHandle.get(key);
16
+ if (handle) {
17
+ syncHandle.delete(key);
18
+ handle.stopSync();
19
+ }
20
+ }
21
+ for (const key of newKeys) {
22
+ if (syncHandle.has(key)) {
23
+ continue;
24
+ }
25
+ const leftRef = computedReadWrite(left, key, options?.leftOptions);
26
+ const rightRef = computedReadWrite(right, key, options?.rightOptions);
27
+ const stopSync = syncRef(leftRef, rightRef);
28
+ syncHandle.set(key, { leftRef, rightRef, stopSync });
29
+ }
30
+ });
31
+ }
32
+ function objectKeysRef(source) {
33
+ const keys = shallowRef([]);
34
+ watchEffect(() => {
35
+ const value = toValue(source);
36
+ keys.value = value ? Object.keys(value) : [];
37
+ });
38
+ return keys;
39
+ }
40
+ function aggregateKeys(options) {
41
+ const leftKeys = !options.keySource || options.keySource === "left" ? objectKeysRef(options.left) : void 0;
42
+ const rightKeys = !options.keySource || options.keySource === "right" ? objectKeysRef(options.right) : void 0;
43
+ return computed(() => {
44
+ if (Array.isArray(options.keySource)) {
45
+ return new Set(options.keySource);
46
+ }
47
+ return /* @__PURE__ */ new Set(
48
+ [...leftKeys?.value ?? [], ...rightKeys?.value ?? []]
49
+ );
50
+ });
51
+ }
52
+ function computedReadWrite(source, key, options) {
53
+ return computed({
54
+ get() {
55
+ const target = toValue(source);
56
+ if (target) {
57
+ return options?.getter ? options.getter(target, key) : target[key];
58
+ }
59
+ return void 0;
60
+ },
61
+ set(val) {
62
+ const target = toValue(source);
63
+ if (target) {
64
+ if (options?.setter) {
65
+ options.setter(target, key, val);
66
+ } else {
67
+ target[key] = val;
68
+ }
69
+ options?.onChange?.(key, val);
70
+ }
71
+ }
72
+ });
73
+ }
@@ -14,6 +14,7 @@ export declare function useReseeUx(): {
14
14
  tooManyOptions: string;
15
15
  };
16
16
  form: {
17
+ submitButtonLabel: string;
17
18
  filterPlaceholder: string;
18
19
  filterNoResults: string;
19
20
  noOptionsAvailable: string;
@@ -10,6 +10,7 @@ const Localization = reactive({
10
10
  tooManyOptions: "Cannot select more than {count} option(s)"
11
11
  },
12
12
  form: {
13
+ submitButtonLabel: "Submit",
13
14
  filterPlaceholder: "Search",
14
15
  filterNoResults: "No Results Found",
15
16
  noOptionsAvailable: "No Options Available",
@@ -1 +1,3 @@
1
- @layer components{.input-label{display:block;-webkit-user-select:none;-moz-user-select:none;user-select:none}.input-label.required:after{color:var(--color-danger);content:"*";display:inline-block;margin-inline-start:--spacing(1)}.input-label.disabled{cursor:not-allowed;opacity:.6}.input-label-pair{display:flex;flex-direction:column;gap:--spacing(1);margin-block-end:--spacing(1)}.input-label-pair.label-after,.input-label-pair.label-before{align-items:center;flex-direction:row;gap:--spacing(3)}.input-label-pair.label-after .input-label,.input-label-pair.label-below .input-label{order:2}.input-validation{color:var(--color-danger);font-size:var(--text-sm);height:0;line-clamp:2}.input-field{display:flex;flex-direction:column}.input-control{flex-grow:1;padding:--spacing(2) --spacing(3)}.input-control::-moz-placeholder{color:var(--color-global-foreground-accent)}.input-control .placeholder,.input-control::placeholder{color:var(--color-global-foreground-accent)}.input-group{align-items:center;display:flex}.input-group.input-group-loading{cursor:wait}.input-group .input-group-addon{color:var(--color-global-foreground-accent);padding:0 --spacing(2)}.input-group button.input-group-addon{cursor:pointer}.input-group .input-control{outline:none}.input-control:where(:not(.input-group .input-control)),.input-group{background-color:var(--color-global-background);border-radius:--spacing(1);cursor:pointer;outline:solid 2px var(--color-background-scale-e);overflow:clip;transition:color,background-color,outline-color,box-shadow;transition-duration:calc(var(--default-transition-duration)*2);width:100%}.input-control:where(:not(.input-group .input-control)):has(input[readonly]:where(:not(.p-hidden-accessible input)),[aria-readonly=true]),.input-control:where(:not(.input-group .input-control)):is(input[readonly]),.input-group:has(input[readonly]:where(:not(.p-hidden-accessible input)),[aria-readonly=true]),.input-group:is(input[readonly]){cursor:default}.input-control:where(:not(.input-group .input-control)):not(:is(input[readonly]),:has(input[readonly]:where(:not(.p-hidden-accessible input)),[aria-readonly=true])):is(:disabled,:has(:disabled,[aria-disabled=true])),.input-group:not(:is(input[readonly]),:has(input[readonly]:where(:not(.p-hidden-accessible input)),[aria-readonly=true])):is(:disabled,:has(:disabled,[aria-disabled=true])){cursor:not-allowed;opacity:.6}.input-control:where(:not(.input-group .input-control)):not(:is(input[readonly]),:has(input[readonly]:where(:not(.p-hidden-accessible input)),[aria-readonly=true])):not(:disabled,:has(:disabled,[aria-disabled=true])):focus-within,.input-control:where(:not(.input-group .input-control)):not(:is(input[readonly]),:has(input[readonly]:where(:not(.p-hidden-accessible input)),[aria-readonly=true])):not(:disabled,:has(:disabled,[aria-disabled=true])):hover,.input-group:not(:is(input[readonly]),:has(input[readonly]:where(:not(.p-hidden-accessible input)),[aria-readonly=true])):not(:disabled,:has(:disabled,[aria-disabled=true])):focus-within,.input-group:not(:is(input[readonly]),:has(input[readonly]:where(:not(.p-hidden-accessible input)),[aria-readonly=true])):not(:disabled,:has(:disabled,[aria-disabled=true])):hover{outline-color:var(--color-global-foreground-accent)}.input-control:where(:not(.input-group .input-control)):not(:is(input[readonly]),:has(input[readonly]:where(:not(.p-hidden-accessible input)),[aria-readonly=true])):not(:disabled,:has(:disabled,[aria-disabled=true])):not(:has(>input[type=checkbox])):focus-within,.input-group:not(:is(input[readonly]),:has(input[readonly]:where(:not(.p-hidden-accessible input)),[aria-readonly=true])):not(:disabled,:has(:disabled,[aria-disabled=true])):not(:has(>input[type=checkbox])):focus-within{background-color:var(--color-background-scale-b);box-shadow:var(--shadow-heavy)}.input-group:where(:has(input[type=checkbox])){flex-shrink:0;height:1.5rem;position:relative;transform:translateY(-1px);-webkit-user-select:none;-moz-user-select:none;user-select:none;width:1.5rem}.input-group:where(:has(input[type=checkbox])) svg{font-size:1rem;height:1rem;line-height:1;margin-left:.25rem;width:1rem}.input-group:where(:has(input[type=checkbox])) input{-webkit-appearance:none;-moz-appearance:none;appearance:none;height:100%;inset:0;opacity:0;position:absolute;z-index:10}.input-group:where(:has(input[type=checkbox])) input:not(:disabled,[readonly]){cursor:pointer}.input-group:where(:has(input[type=checkbox])).toggle-switch{border-radius:1rem;width:2.5rem}.input-group:where(:has(input[type=checkbox])).toggle-switch:has(:checked) .slider:before{background-color:var(--color-global-foreground);transform:translateX(1rem)}.input-group:where(:has(input[type=checkbox])).toggle-switch .slider{border-radius:1rem;inset:0;position:absolute}.input-group:where(:has(input[type=checkbox])).toggle-switch .slider:before{background-color:var(--color-background-scale-d);border-radius:var(--radius-full);box-shadow:var(--shadow-md);content:"";height:1rem;left:.25rem;position:absolute;top:.25rem;transition:transform,background-color;transition-duration:var(--default-transition-duration);width:1rem}.input-menu .input-control,.input-menu .input-group{background-color:transparent}.input-menu .input-group:where(:has(input[type=checkbox])){height:1.2rem;width:1.2rem}.input-menu .input-group:where(:has(input[type=checkbox])) svg{margin-left:.125rem}[aria-disabled=true] .input-menu .input-group:where(:has(input[type=checkbox])):focus-within,[aria-disabled=true] .input-menu .input-group:where(:has(input[type=checkbox])):hover{outline-color:var(--color-background-scale-e)!important}[aria-disabled=true] .input-menu .input-group:where(:has(input[type=checkbox])):focus-within input,[aria-disabled=true] .input-menu .input-group:where(:has(input[type=checkbox])):hover input{cursor:not-allowed!important}.input-menu-header{align-items:center;display:flex;gap:--spacing(2)}.input-menu-header .input-menu-filter{align-items:center;color:var(--color-global-foreground-accent);display:flex;flex-grow:1;transition:color var(--default-transition-duration) var(--default-transition-timing-function)}.input-menu-header .input-menu-filter input{flex-grow:1;outline:none;padding:--spacing(.5) 0}.input-menu-header .input-menu-filter input::-moz-placeholder{color:var(--color-global-foreground-accent)}.input-menu-header .input-menu-filter input::placeholder{color:var(--color-global-foreground-accent)}.input-menu-header .input-menu-filter:focus-within{color:var(--color-global-foreground)}}
1
+ @layer components{.input-label{display:block;-webkit-user-select:none;-moz-user-select:none;user-select:none}.input-label.required:after{color:var(--color-danger);content:"*";display:inline-block;margin-inline-start:--spacing(1)}.input-label.disabled{cursor:not-allowed;opacity:.6}.input-label-pair{display:flex;flex-direction:column;gap:--spacing(1);margin-block-end:--spacing(1)}.input-label-pair.label-after,.input-label-pair.label-before{align-items:center;flex-direction:row;gap:--spacing(3)}.input-label-pair.label-after .input-label,.input-label-pair.label-below .input-label{order:2}.input-validation{color:var(--color-danger);font-size:var(--text-sm);height:0;line-clamp:2}.input-field{display:flex;flex-direction:column}.input-control{flex-grow:1;padding:--spacing(2) --spacing(3)}.input-control::-moz-placeholder{color:var(--color-global-foreground-accent)}.input-control .placeholder,.input-control::placeholder{color:var(--color-global-foreground-accent)}.input-group{align-items:center;display:flex}.input-group.input-group-loading{cursor:wait}.input-group .input-group-addon{color:var(--color-global-foreground-accent);padding:0 --spacing(2)}.input-group button.input-group-addon{cursor:pointer}.input-group .input-control{outline:none}.input-control:where(:not(.input-group .input-control)),.input-group{background-color:var(--color-global-background);border-radius:--spacing(1);cursor:pointer;outline:solid 2px var(--color-background-scale-e);overflow:clip;transition:color,background-color,outline-color,box-shadow;transition-duration:calc(var(--default-transition-duration)*2);width:100%}.input-control:where(:not(.input-group .input-control)):where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-control:where(:not(.input-group .input-control)))),.input-group:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-group)){cursor:default}.input-control:where(:not(.input-group .input-control)):not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-control:where(:not(.input-group .input-control))))):where(.disabled,:disabled:not(.p-hidden-accessible input),:is(.disabled .input-control:where(:not(.input-group .input-control)):not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-control:where(:not(.input-group .input-control))))))),.input-group:not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-group))):where(.disabled,:disabled:not(.p-hidden-accessible input),:is(.disabled .input-group:not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-group))))){cursor:not-allowed;opacity:.6}.input-control:where(:not(.input-group .input-control)):not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-control:where(:not(.input-group .input-control))))):not(:where(.disabled,:disabled:not(.p-hidden-accessible input),:is(.disabled .input-control:where(:not(.input-group .input-control)):not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-control:where(:not(.input-group .input-control)))))))):focus-within,.input-control:where(:not(.input-group .input-control)):not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-control:where(:not(.input-group .input-control))))):not(:where(.disabled,:disabled:not(.p-hidden-accessible input),:is(.disabled .input-control:where(:not(.input-group .input-control)):not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-control:where(:not(.input-group .input-control)))))))):hover,.input-group:not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-group))):not(:where(.disabled,:disabled:not(.p-hidden-accessible input),:is(.disabled .input-group:not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-group)))))):focus-within,.input-group:not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-group))):not(:where(.disabled,:disabled:not(.p-hidden-accessible input),:is(.disabled .input-group:not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-group)))))):hover{outline-color:var(--color-global-foreground-accent)}.input-control:where(:not(.input-group .input-control)):not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-control:where(:not(.input-group .input-control))))):not(:where(.disabled,:disabled:not(.p-hidden-accessible input),:is(.disabled .input-control:where(:not(.input-group .input-control)):not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-control:where(:not(.input-group .input-control)))))))):focus-within,.input-group:not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-group))):not(:where(.disabled,:disabled:not(.p-hidden-accessible input),:is(.disabled .input-group:not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-group)))))):focus-within{box-shadow:var(--shadow-heavy)}.input-control:where(:not(.input-group .input-control)):not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-control:where(:not(.input-group .input-control))))):not(:where(.disabled,:disabled:not(.p-hidden-accessible input),:is(.disabled .input-control:where(:not(.input-group .input-control)):not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-control:where(:not(.input-group .input-control)))))))):not(:has(>input[type=checkbox]),.input-button-bar):focus-within,.input-group:not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-group))):not(:where(.disabled,:disabled:not(.p-hidden-accessible input),:is(.disabled .input-group:not(:where(.readonly,[readonly]:not(.p-hidden-accessible input),:is(.readonly .input-group)))))):not(:has(>input[type=checkbox]),.input-button-bar):focus-within{background-color:var(--color-background-scale-b)}.input-group:where(:has(input[type=checkbox])){flex-shrink:0;height:1.5rem;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:1.5rem}
2
+
3
+ /* !important is to overwrite what gets attached to i-* icons in the utility layer */.input-group:where(:has(input[type=checkbox])) span[class^=i-],.input-group:where(:has(input[type=checkbox])) svg{display:block!important;font-size:1rem;height:1rem!important;line-height:1;margin-left:.25rem;width:1rem!important}.input-group:where(:has(input[type=checkbox])) input{-webkit-appearance:none;-moz-appearance:none;appearance:none;height:100%;inset:0;opacity:0;position:absolute;z-index:10}.input-group:where(:has(input[type=checkbox])) input:not(:disabled,[readonly]){cursor:pointer}.input-group:where(:has(input[type=checkbox])).toggle-switch{border-radius:1rem;width:2.5rem}.input-group:where(:has(input[type=checkbox])).toggle-switch:has(:checked) .slider:before{background-color:var(--color-global-foreground);transform:translateX(1rem)}.input-group:where(:has(input[type=checkbox])).toggle-switch .slider{border-radius:1rem;inset:0;position:absolute}.input-group:where(:has(input[type=checkbox])).toggle-switch .slider:before{background-color:var(--color-background-scale-d);border-radius:var(--radius-full);box-shadow:var(--shadow-md);content:"";height:1rem;left:.25rem;position:absolute;top:.25rem;transition:transform,background-color;transition-duration:var(--default-transition-duration);width:1rem}.input-menu .input-control,.input-menu .input-group{background-color:transparent}.input-menu .input-group:where(:has(input[type=checkbox])){height:1.2rem;width:1.2rem}.input-menu .input-group:where(:has(input[type=checkbox])) span[class^=i-],.input-menu .input-group:where(:has(input[type=checkbox])) svg{margin-left:.1rem;margin-top:-.1rem}[aria-disabled=true] .input-menu .input-group:where(:has(input[type=checkbox])):focus-within,[aria-disabled=true] .input-menu .input-group:where(:has(input[type=checkbox])):hover{outline-color:var(--color-background-scale-e)!important}[aria-disabled=true] .input-menu .input-group:where(:has(input[type=checkbox])):focus-within input,[aria-disabled=true] .input-menu .input-group:where(:has(input[type=checkbox])):hover input{cursor:not-allowed!important}.input-menu-header{align-items:center;display:flex;gap:--spacing(2)}.input-menu-header .input-menu-filter{align-items:center;color:var(--color-global-foreground-accent);display:flex;flex-grow:1;transition:color var(--default-transition-duration) var(--default-transition-timing-function)}.input-menu-header .input-menu-filter input{flex-grow:1;outline:none;padding:--spacing(.5) 0}.input-menu-header .input-menu-filter input::-moz-placeholder{color:var(--color-global-foreground-accent)}.input-menu-header .input-menu-filter input::placeholder{color:var(--color-global-foreground-accent)}.input-menu-header .input-menu-filter:focus-within{color:var(--color-global-foreground)}.input-button-bar{gap:--spacing(.5);padding:--spacing(.5);width:-moz-fit-content;width:fit-content}.input-button-bar button{cursor:pointer;padding:--spacing(1.5) --spacing(2);transition:background-color var(--default-transition-duration) var(--default-transition-timing-function)}.input-button-bar button[aria-pressed=true]{background-color:var(--color-background-scale-f)}.input-button-bar button:where(.readonly button){cursor:default}.input-button-bar button:disabled:not(:where(.readonly button)){cursor:not-allowed;opacity:.6}.input-button-bar button:not(:disabled,:where(.readonly button),[aria-pressed=true]):focus-visible,.input-button-bar button:not(:disabled,:where(.readonly button),[aria-pressed=true]):hover{background-color:var(--color-background-scale-b)}.input-button-bar button:first-child{border-bottom-left-radius:var(--radius-sm);border-top-left-radius:var(--radius-sm)}.input-button-bar button:last-child{border-bottom-right-radius:var(--radius-sm);border-top-right-radius:var(--radius-sm)}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@resee-movies/nuxt-ux",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "The next-gen user experience library for ReSee Movies - currently in development. ",
5
5
  "repository": {
6
6
  "url": "https://github.com/ReSee-Movies/nuxt-ux.git"
@@ -35,7 +35,7 @@
35
35
  "dist"
36
36
  ],
37
37
  "scripts": {
38
- "dev": "npm run dev:prepare && nuxi dev playground",
38
+ "dev": "npm run dev:prepare && nuxi dev playground --local --port 3003",
39
39
  "dev:preview": "npm run dev:build && nuxi preview playground",
40
40
  "dev:build": "nuxi build playground",
41
41
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",