vueless 0.0.492 → 0.0.494

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 (35) hide show
  1. package/constants.js +1 -1
  2. package/index.ts +2 -1
  3. package/package.json +1 -1
  4. package/preset-tailwind.js +1 -1
  5. package/types.ts +37 -0
  6. package/ui.form-calendar/UCalendar.vue +20 -11
  7. package/ui.form-calendar/UCalendarDayView.vue +1 -1
  8. package/ui.form-calendar/UCalendarMonthView.vue +1 -1
  9. package/ui.form-calendar/UCalendarYearView.vue +1 -1
  10. package/ui.form-calendar/config.ts +1 -0
  11. package/ui.form-calendar/constants.ts +0 -6
  12. package/ui.form-calendar/storybook/stories.ts +5 -3
  13. package/ui.form-calendar/types.ts +7 -2
  14. package/ui.form-calendar/useAttrs.ts +1 -1
  15. package/ui.form-calendar/utilDate.ts +2 -2
  16. package/ui.form-date-picker/UDatePicker.vue +18 -16
  17. package/ui.form-date-picker/storybook/stories.ts +6 -4
  18. package/ui.form-date-picker/types.ts +2 -6
  19. package/ui.form-date-picker/useAttrs.ts +1 -1
  20. package/ui.form-date-picker-range/UDatePickerRange.vue +371 -433
  21. package/ui.form-date-picker-range/UDatePickerRangeInputs.vue +67 -76
  22. package/ui.form-date-picker-range/UDatePickerRangePeriodMenu.vue +158 -205
  23. package/ui.form-date-picker-range/{constants.js → constants.ts} +17 -18
  24. package/ui.form-date-picker-range/storybook/Docs.mdx +16 -0
  25. package/ui.form-date-picker-range/storybook/stories.ts +237 -0
  26. package/ui.form-date-picker-range/types.ts +193 -0
  27. package/ui.form-date-picker-range/{useAttrs.js → useAttrs.ts} +21 -5
  28. package/ui.form-date-picker-range/useLocale.ts +65 -0
  29. package/ui.form-date-picker-range/{useUserFormat.js → useUserFormat.ts} +22 -8
  30. package/ui.form-date-picker-range/{utilDateRange.js → utilDateRange.ts} +14 -8
  31. package/ui.form-date-picker-range/{utilValidation.js → utilValidation.ts} +4 -4
  32. package/utils/theme.ts +19 -5
  33. package/web-types.json +158 -52
  34. package/ui.form-date-picker-range/useLocale.js +0 -63
  35. /package/ui.form-date-picker-range/{config.js → config.ts} +0 -0
package/constants.js CHANGED
@@ -19,7 +19,7 @@ export const DEFAULT_GRAY_COLOR = COOL_COLOR;
19
19
  export const DEFAULT_RING = 4; /* pixels */
20
20
  export const DEFAULT_RING_OFFSET = 0; /* pixels */
21
21
  export const DEFAULT_RING_OFFSET_COLOR_LIGHT = "#ffffff"; // white
22
- export const DEFAULT_RING_OFFSET_COLOR_DARK = "#1f2937"; // gray-800
22
+ export const DEFAULT_RING_OFFSET_COLOR_DARK = "#111827"; // gray-900
23
23
  export const DEFAULT_ROUNDING = 8; /* pixels */
24
24
 
25
25
  /* Vueless supported colors and shades */
package/index.ts CHANGED
@@ -38,7 +38,8 @@ export function createVueless(options: CreateVuelessOptions = {}) {
38
38
  app.provide(LoaderProgressSymbol, loaderProgress);
39
39
  };
40
40
 
41
- themeInit();
41
+ /* init theme after first render */
42
+ setTimeout(themeInit, 0);
42
43
 
43
44
  return {
44
45
  install,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "0.0.492",
3
+ "version": "0.0.494",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [
@@ -96,7 +96,7 @@ export const vuelessTailwindConfig = {
96
96
  dynamic: "var(--vl-ring-offset)",
97
97
  },
98
98
  ringOffsetColor: {
99
- "color-dynamic": twColorWithOpacity("--vl-ring-offset-color"),
99
+ DEFAULT: twColorWithOpacity("--vl-ring-offset-color"),
100
100
  },
101
101
  },
102
102
  configViewer: {
package/types.ts CHANGED
@@ -6,6 +6,7 @@ import UButtonDefaultConfig from "./ui.button/config.ts";
6
6
  import UBadgeDefaultConfig from "./ui.text-badge/config.ts";
7
7
  import UCalendarDefaultConfig from "./ui.form-calendar/config.ts";
8
8
  import UDatePickerConfig from "./ui.form-date-picker/config.ts";
9
+ import UDatePickerRangeConfig from "./ui.form-date-picker-range/config.ts";
9
10
 
10
11
  import type { ComputedRef, MaybeRef, Ref } from "vue";
11
12
  import type { Props } from "tippy.js";
@@ -117,6 +118,7 @@ export interface Components {
117
118
  UBadge?: Partial<typeof UBadgeDefaultConfig>;
118
119
  UCalendar?: Partial<typeof UCalendarDefaultConfig>;
119
120
  UDatePicker?: Partial<typeof UDatePickerConfig>;
121
+ UDatePickerRange?: Partial<typeof UDatePickerRangeConfig>;
120
122
  }
121
123
 
122
124
  export interface Directives {
@@ -329,3 +331,38 @@ export interface ExposeProperty {
329
331
  type: string;
330
332
  description?: string;
331
333
  }
334
+ /**
335
+ * Utility types to extract component props, slots, emit, exposed types.
336
+ * Original code taken from `vue-component-type-helpers` npm package.
337
+ * Source code: https://github.com/vuejs/language-tools/blob/master/packages/component-type-helpers/index.ts
338
+ */
339
+
340
+ /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-object-type */
341
+ export type ComponentType<T> = T extends new (...args: any) => {}
342
+ ? 1
343
+ : T extends (...args: any) => any
344
+ ? 2
345
+ : 0;
346
+
347
+ export type ComponentProps<T> = T extends new (...args: any) => { $props: infer P }
348
+ ? NonNullable<P>
349
+ : T extends (props: infer P, ...args: any) => any
350
+ ? P
351
+ : {};
352
+
353
+ export type ComponentSlots<T> = T extends new (...args: any) => { $slots: infer S }
354
+ ? NonNullable<S>
355
+ : T extends (props: any, ctx: { slots: infer S; attrs: any; emit: any }, ...args: any) => any
356
+ ? NonNullable<S>
357
+ : {};
358
+
359
+ export type ComponentEmit<T> = T extends new (...args: any) => { $emit: infer E }
360
+ ? NonNullable<E>
361
+ : {};
362
+
363
+ export type ComponentExposed<T> = T extends new (...args: any) => infer E
364
+ ? E
365
+ : T extends (props: any, ctx: any, expose: (exposed: infer E) => any, ...args: any) => any
366
+ ? NonNullable<E>
367
+ : {};
368
+ /* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-object-type */
@@ -1,4 +1,4 @@
1
- <script setup lang="ts">
1
+ <script setup lang="ts" generic="TModelValue extends DateValue">
2
2
  import { computed, ref, watch, useTemplateRef } from "vue";
3
3
  import { merge } from "lodash-es";
4
4
 
@@ -50,14 +50,16 @@ type DefaultLocale = typeof defaultConfig.i18n;
50
50
 
51
51
  defineOptions({ inheritAttrs: false });
52
52
 
53
- const props = withDefaults(defineProps<UCalendarProps>(), {
53
+ type Props = UCalendarProps<TModelValue>;
54
+ const props = withDefaults(defineProps<Props>(), {
54
55
  view: View.Day,
55
- range: getDefault<UCalendarProps>(defaultConfig, UCalendar).range,
56
- timepicker: getDefault<UCalendarProps>(defaultConfig, UCalendar).timepicker,
57
- dateFormat: getDefault<UCalendarProps>(defaultConfig, UCalendar).dateFormat,
58
- dateTimeFormat: getDefault<UCalendarProps>(defaultConfig, UCalendar).dateTimeFormat,
59
- userDateFormat: getDefault<UCalendarProps>(defaultConfig, UCalendar).userDateFormat,
60
- userDateTimeFormat: getDefault<UCalendarProps>(defaultConfig, UCalendar).userDateTimeFormat,
56
+ range: getDefault<Props>(defaultConfig, UCalendar).range,
57
+ timepicker: getDefault<Props>(defaultConfig, UCalendar).timepicker,
58
+ dateFormat: getDefault<Props>(defaultConfig, UCalendar).dateFormat,
59
+ dateTimeFormat: getDefault<Props>(defaultConfig, UCalendar).dateTimeFormat,
60
+ userDateFormat: getDefault<Props>(defaultConfig, UCalendar).userDateFormat,
61
+ userDateTimeFormat: getDefault<Props>(defaultConfig, UCalendar).userDateTimeFormat,
62
+ tabindex: getDefault<Props>(defaultConfig, UCalendar).tabindex,
61
63
  dataTest: "",
62
64
  config: () => ({}),
63
65
  });
@@ -208,8 +210,15 @@ const userFormatLocale = computed(() => {
208
210
  const localValue = computed({
209
211
  get: () => {
210
212
  if (props.range) {
211
- const from = isRangeDate(props.modelValue) ? props.modelValue.from : props.modelValue || null;
212
- const to = isRangeDate(props.modelValue) ? props.modelValue.to : null;
213
+ const isModelValueRangeType =
214
+ typeof props.modelValue === "object" && !(props.modelValue instanceof Date);
215
+
216
+ const modelValue = isModelValueRangeType
217
+ ? (props.modelValue as RangeDate)
218
+ : (props.modelValue as string | Date);
219
+
220
+ const from = isRangeDate(modelValue) ? modelValue.from : modelValue || null;
221
+ const to = isRangeDate(modelValue) ? modelValue.to : null;
213
222
 
214
223
  return {
215
224
  from: parseDate(from || null, actualDateFormat.value, locale.value),
@@ -651,7 +660,7 @@ defineExpose({
651
660
  </script>
652
661
 
653
662
  <template>
654
- <div ref="wrapper" tabindex="1" v-bind="wrapperAttrs" @keydown="onKeydown">
663
+ <div ref="wrapper" :tabindex="tabindex" v-bind="wrapperAttrs" @keydown="onKeydown">
655
664
  <div v-bind="navigationAttrs">
656
665
  <UButton
657
666
  square
@@ -40,7 +40,7 @@ const {
40
40
  activeDayAttrs,
41
41
  currentLastDayInRangeAttrs,
42
42
  currentFirstDayInRangeAttrs,
43
- } = useAttrs(props as unknown as UCalendarProps);
43
+ } = useAttrs(props as unknown as UCalendarProps<unknown>);
44
44
 
45
45
  const localSelectedDate = computed(() => {
46
46
  return props.selectedDate === null ? getDateWithoutTime() : props.selectedDate;
@@ -30,7 +30,7 @@ const {
30
30
  currentLastMonthInRangeAttrs,
31
31
  currentFirstMonthInRangeAttrs,
32
32
  singleCurrentMonthInRangeAttrs,
33
- } = useAttrs(props as unknown as UCalendarProps);
33
+ } = useAttrs(props as unknown as UCalendarProps<unknown>);
34
34
 
35
35
  const localSelectedDate = computed(() => {
36
36
  return props.selectedDate === null ? getDateWithoutTime() : props.selectedDate;
@@ -30,7 +30,7 @@ const {
30
30
  singleCurrentYearInRangeAttrs,
31
31
  currentLastYearInRangeAttrs,
32
32
  currentFirstYearInRangeAttrs,
33
- } = useAttrs(props as unknown as UCalendarProps);
33
+ } = useAttrs(props as unknown as UCalendarProps<unknown>);
34
34
 
35
35
  const localSelectedDate = computed(() => {
36
36
  return props.selectedDate === null ? getDateWithoutTime() : props.selectedDate;
@@ -153,6 +153,7 @@ export default /*tw*/ {
153
153
  timepicker: false,
154
154
  dateFormat: undefined,
155
155
  dateTimeFormat: undefined,
156
+ tabindex: 1,
156
157
  /* icons */
157
158
  viewSwitchIcon: "keyboard_arrow_down",
158
159
  nextIcon: "keyboard_arrow_right",
@@ -49,12 +49,6 @@ export enum InputType {
49
49
  Seconds,
50
50
  }
51
51
 
52
- // TODO: Remove redundant arrays when other components migrated to ts;
53
- export const LOCALE_TYPE = {
54
- day: "day",
55
- month: "month",
56
- };
57
-
58
52
  export const ARROW_KEYS: string[] = [
59
53
  KeyCode.ArrowLeft,
60
54
  KeyCode.ArrowUp,
@@ -3,9 +3,11 @@ import { getArgTypes, getSlotNames, getSlotsFragment } from "../../utils/storybo
3
3
 
4
4
  import UCalendar from "../../ui.form-calendar/UCalendar.vue";
5
5
 
6
+ import { UCalendar as UCalendarName } from "../constants.ts";
7
+
6
8
  import type { UCalendarProps } from "../types.ts";
7
9
 
8
- interface UCalendarArgs extends UCalendarProps {
10
+ interface UCalendarArgs extends UCalendarProps<unknown> {
9
11
  slotTemplate?: string;
10
12
  enum: "size";
11
13
  }
@@ -19,7 +21,7 @@ export default {
19
21
  component: UCalendar,
20
22
  args: {},
21
23
  argTypes: {
22
- ...getArgTypes(UCalendar.__name),
24
+ ...getArgTypes(UCalendarName),
23
25
  },
24
26
  parameters: {
25
27
  docs: {
@@ -33,7 +35,7 @@ export default {
33
35
  const DefaultTemplate: StoryFn<UCalendarArgs> = (args: UCalendarArgs) => ({
34
36
  components: { UCalendar },
35
37
  setup() {
36
- const slots = getSlotNames(UCalendar.__name);
38
+ const slots = getSlotNames(UCalendarName);
37
39
 
38
40
  return { args, slots };
39
41
  },
@@ -15,11 +15,11 @@ export function isRangeDate(value: Date | string | RangeDate | null): value is R
15
15
  return !(value instanceof Date || typeof value === "string") && value !== null;
16
16
  }
17
17
 
18
- export interface UCalendarProps {
18
+ export interface UCalendarProps<TModelValue> {
19
19
  /**
20
20
  * Calendar value (JavaScript Date object or string formatted in given `dateFormat` or object when `range` enabled).
21
21
  */
22
- modelValue: DateValue;
22
+ modelValue: TModelValue;
23
23
 
24
24
  /**
25
25
  * Calendar view variant.
@@ -31,6 +31,11 @@ export interface UCalendarProps {
31
31
  */
32
32
  range?: boolean;
33
33
 
34
+ /**
35
+ * Controls the keyboard “Tab” focus order of elements.
36
+ */
37
+ tabindex?: number | string;
38
+
34
39
  /**
35
40
  * Show timepicker.
36
41
  */
@@ -6,7 +6,7 @@ import defaultConfig from "./config.js";
6
6
  import type { UseAttrs } from "../types.ts";
7
7
  import type { UCalendarProps, Config } from "./types.ts";
8
8
 
9
- export default function useAttrs(props: UCalendarProps): UseAttrs<Config> {
9
+ export default function useAttrs(props: UCalendarProps<unknown>): UseAttrs<Config> {
10
10
  const { config, getKeysAttrs, hasSlotContent, getExtendingKeysClasses } = useUI<Config>(
11
11
  defaultConfig,
12
12
  () => props.config,
@@ -1,4 +1,4 @@
1
- import { LOCALE_TYPE, DAYS_IN_WEEK, SECONDS_IN_MINUTES } from "./constants.ts";
1
+ import { LocaleType, DAYS_IN_WEEK, SECONDS_IN_MINUTES } from "./constants.ts";
2
2
 
3
3
  export type dateSettings = { weekStartsOn?: number };
4
4
 
@@ -146,7 +146,7 @@ export function getStartOfDay(date: Date) {
146
146
  }
147
147
 
148
148
  export function getSortedLocale<TLocale>(locale: TLocale, type: "month" | "day"): string[] {
149
- const targetMap = type === LOCALE_TYPE.month ? monthsMap : daysMap;
149
+ const targetMap = type === LocaleType.Month ? monthsMap : daysMap;
150
150
 
151
151
  if (typeof locale === "object" && !Array.isArray(locale)) {
152
152
  const sortedDays = Object.entries(locale as object)
@@ -1,4 +1,4 @@
1
- <script setup lang="ts">
1
+ <script setup lang="ts" generic="TModelValue extends string | Date">
2
2
  import { computed, nextTick, ref, useId, useTemplateRef } from "vue";
3
3
  import { merge } from "lodash-es";
4
4
 
@@ -20,22 +20,24 @@ import defaultConfig from "./config.js";
20
20
  import { UDatePicker } from "./constants.js";
21
21
 
22
22
  import type { UDatePickerProps } from "./types.ts";
23
+ import type { ComponentExposed } from "../types.ts";
23
24
 
24
25
  defineOptions({ inheritAttrs: false });
25
26
 
26
- const props = withDefaults(defineProps<UDatePickerProps>(), {
27
- labelAlign: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).labelAlign,
28
- size: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).size,
29
- openDirectionX: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).openDirectionX,
30
- openDirectionY: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).openDirectionY,
31
- timepicker: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).timepicker,
32
- dateFormat: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).dateFormat,
33
- dateTimeFormat: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).dateTimeFormat,
34
- userDateFormat: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).userDateFormat,
35
- userDateTimeFormat: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).userDateTimeFormat,
36
- leftIcon: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).leftIcon,
37
- rightIcon: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).rightIcon,
38
- disabled: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).disabled,
27
+ type Props = UDatePickerProps<TModelValue>;
28
+ const props = withDefaults(defineProps<Props>(), {
29
+ labelAlign: getDefault<Props>(defaultConfig, UDatePicker).labelAlign,
30
+ size: getDefault<Props>(defaultConfig, UDatePicker).size,
31
+ openDirectionX: getDefault<Props>(defaultConfig, UDatePicker).openDirectionX,
32
+ openDirectionY: getDefault<Props>(defaultConfig, UDatePicker).openDirectionY,
33
+ timepicker: getDefault<Props>(defaultConfig, UDatePicker).timepicker,
34
+ dateFormat: getDefault<Props>(defaultConfig, UDatePicker).dateFormat,
35
+ dateTimeFormat: getDefault<Props>(defaultConfig, UDatePicker).dateTimeFormat,
36
+ userDateFormat: getDefault<Props>(defaultConfig, UDatePicker).userDateFormat,
37
+ userDateTimeFormat: getDefault<Props>(defaultConfig, UDatePicker).userDateTimeFormat,
38
+ leftIcon: getDefault<Props>(defaultConfig, UDatePicker).leftIcon,
39
+ rightIcon: getDefault<Props>(defaultConfig, UDatePicker).rightIcon,
40
+ disabled: getDefault<Props>(defaultConfig, UDatePicker).disabled,
39
41
  dataTest: "",
40
42
  config: () => ({}),
41
43
  });
@@ -64,7 +66,7 @@ const formattedDate = ref("");
64
66
  const customView = ref(View.Day);
65
67
 
66
68
  const wrapperRef = useTemplateRef<HTMLDivElement>("wrapper");
67
- const calendarRef = useTemplateRef<InstanceType<typeof UCalendar>>("calendar");
69
+ const calendarRef = useTemplateRef<ComponentExposed<typeof UCalendar>>("calendar");
68
70
 
69
71
  const calendarWrapperRef = computed(() => calendarRef?.value?.wrapperRef || null);
70
72
 
@@ -233,7 +235,7 @@ defineExpose({
233
235
  ref="calendarRef"
234
236
  v-model="localValue"
235
237
  v-model:view="customView"
236
- tabindex="-1"
238
+ :tabindex="-1"
237
239
  :timepicker="timepicker"
238
240
  :date-format="dateFormat"
239
241
  :date-time-format="dateTimeFormat"
@@ -5,13 +5,15 @@ import UDatePicker from "../../ui.form-date-picker/UDatePicker.vue";
5
5
  import UIcon from "../../ui.image-icon/UIcon.vue";
6
6
  import URow from "../../ui.container-row/URow.vue";
7
7
 
8
+ import { UDatePicker as UDatePickerName } from "../constants.ts";
9
+
8
10
  import type { UDatePickerProps } from "../types.ts";
9
11
 
10
- interface DefaultUDatePickerArgs extends UDatePickerProps {
12
+ interface DefaultUDatePickerArgs extends UDatePickerProps<unknown> {
11
13
  slotTemplate?: string;
12
14
  }
13
15
 
14
- interface EnumUDatePickerArgs extends UDatePickerProps {
16
+ interface EnumUDatePickerArgs extends UDatePickerProps<unknown> {
15
17
  slotTemplate?: string;
16
18
  enum: "size";
17
19
  }
@@ -28,7 +30,7 @@ export default {
28
30
  modelValue: null,
29
31
  },
30
32
  argTypes: {
31
- ...getArgTypes(UDatePicker.__name),
33
+ ...getArgTypes(UDatePickerName),
32
34
  },
33
35
  parameters: {
34
36
  docs: {
@@ -42,7 +44,7 @@ export default {
42
44
  const DefaultTemplate: StoryFn<DefaultUDatePickerArgs> = (args: DefaultUDatePickerArgs) => ({
43
45
  components: { UDatePicker, UIcon },
44
46
  setup() {
45
- const slots = getSlotNames(UDatePicker.__name);
47
+ const slots = getSlotNames(UDatePickerName);
46
48
 
47
49
  return { args, slots };
48
50
  },
@@ -2,11 +2,11 @@ import defaultConfig from "./config.ts";
2
2
 
3
3
  export type Config = Partial<typeof defaultConfig>;
4
4
 
5
- export interface UDatePickerProps {
5
+ export interface UDatePickerProps<TModelValue> {
6
6
  /**
7
7
  * Calendar value (JavaScript Date object or string formatted in given `dateFormat` or object when `range` enabled).
8
8
  */
9
- modelValue: Date | string;
9
+ modelValue: TModelValue;
10
10
 
11
11
  /**
12
12
  * Datepicker label.
@@ -15,7 +15,6 @@ export interface UDatePickerProps {
15
15
 
16
16
  /**
17
17
  * Datepicker label placement.
18
- * @values top, topInside, topWithDesc, left, right
19
18
  */
20
19
  labelAlign?: "top" | "topInside" | "topWithDesc" | "left" | "right";
21
20
 
@@ -36,19 +35,16 @@ export interface UDatePickerProps {
36
35
 
37
36
  /**
38
37
  * Datepicker size.
39
- * @values sm, md, lg
40
38
  */
41
39
  size?: "sm" | "md" | "lg";
42
40
 
43
41
  /**
44
42
  * Datepicker open direction on x-axis.
45
- * @values auto, left, right
46
43
  */
47
44
  openDirectionX?: "auto" | "left" | "right";
48
45
 
49
46
  /**
50
47
  * Datepicker open direction on y-axis.
51
- * @values auto, top, bottom
52
48
  */
53
49
  openDirectionY?: "auto" | "top" | "bottom";
54
50
 
@@ -15,7 +15,7 @@ interface DatePickerState {
15
15
  }
16
16
 
17
17
  export default function useAttrs(
18
- props: UDatePickerProps,
18
+ props: UDatePickerProps<unknown>,
19
19
  { isTop, isRight }: DatePickerState,
20
20
  ): UseAttrs<Config> {
21
21
  const { config, getKeysAttrs, hasSlotContent } = useUI(defaultConfig, () => props.config);