@dynect/base 0.10.2 → 0.10.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynect/base",
3
- "version": "0.10.2",
3
+ "version": "0.10.4",
4
4
  "description": "Reusable Nuxt base module — components, composables, utils, plugins and i18n from the Dynect design system.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/module.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { addComponentsDir, addImports, addImportsDir, addPlugin, createResolver, defineNuxtModule, installModule } from '@nuxt/kit';
2
+ import { defu } from 'defu';
2
3
  import { existsSync } from 'node:fs';
3
4
  import { join } from 'node:path';
4
5
 
@@ -45,7 +46,7 @@ export default defineNuxtModule<DynectBaseOptions>({
45
46
  veeValidate: {},
46
47
  colorMode: {},
47
48
  i18n: {},
48
- shadcn: { prefix: '', componentDir: '~/components/ui' },
49
+ shadcn: { prefix: '' },
49
50
  icon: {},
50
51
  plugins: { toast: true, ssrWidth: true },
51
52
  },
@@ -96,67 +97,78 @@ export default defineNuxtModule<DynectBaseOptions>({
96
97
  }
97
98
 
98
99
  // ── Install required Nuxt modules ────────────────────────────────────────
100
+ // installModule is marked @deprecated in @nuxt/kit but is the only practical
101
+ // API for installing sub-modules with dynamic options during a module's setup.
99
102
  if (options.shadcn !== false) {
100
- const shadcnComponentDir = isStandalone ? join(runtimeComponentsDir, 'ui') : '~/components/ui';
103
+ // Extract componentDir separately keeping it out of defaults prevents
104
+ // defu from always populating it, which would override the computed path.
105
+ const { componentDir: userComponentDir, ...shadcnRest } = (options.shadcn ?? {}) as { prefix?: string; componentDir?: string };
106
+ const shadcnComponentDir = userComponentDir ?? (isStandalone ? join(runtimeComponentsDir, 'ui') : '~/components/ui');
101
107
 
102
- await installModule('shadcn-nuxt', {
103
- prefix: '',
104
- componentDir: shadcnComponentDir,
105
- ...options.shadcn,
106
- });
108
+ await installModule('shadcn-nuxt', { prefix: '', ...shadcnRest, componentDir: shadcnComponentDir }); // NOSONAR
107
109
  }
108
110
 
109
111
  if (options.veeValidate !== false) {
110
- await installModule('@vee-validate/nuxt', options.veeValidate ?? {});
112
+ await installModule('@vee-validate/nuxt', options.veeValidate ?? {}); // NOSONAR
111
113
  }
112
114
 
113
115
  if (options.colorMode !== false) {
114
- await installModule('@nuxtjs/color-mode', {
115
- preference: 'system',
116
- fallback: 'light',
117
- classPrefix: '',
118
- classSuffix: '',
119
- storage: 'cookie',
120
- storageKey: 'dynect_color_mode',
121
- ...options.colorMode,
122
- });
116
+ // defu(user, defaults): user keys win; nested objects are deep-merged, not replaced
117
+ await installModule(
118
+ '@nuxtjs/color-mode',
119
+ defu(options.colorMode ?? {}, {
120
+ // NOSONAR
121
+ preference: 'system',
122
+ fallback: 'light',
123
+ classPrefix: '',
124
+ classSuffix: '',
125
+ storage: 'cookie',
126
+ storageKey: 'dynect_color_mode',
127
+ })
128
+ );
123
129
  }
124
130
 
125
131
  if (options.i18n !== false) {
126
132
  const langDir = isStandalone ? resolver.resolve('./runtime/assets/lang') : resolver.resolve('../../../app/assets/lang');
127
133
 
128
- await installModule('@nuxtjs/i18n', {
129
- locales: [
130
- { code: 'en', iso: 'en_US', file: 'en.json', name: 'English' },
131
- { code: 'ms', iso: 'ms_MY', file: 'ms.json', name: 'Bahasa' },
132
- ],
133
- langDir,
134
- defaultLocale: 'en',
135
- strategy: 'no_prefix',
136
- detectBrowserLanguage: {
137
- useCookie: true,
138
- cookieKey: 'dynect_language',
139
- cookieSecure: true,
140
- redirectOn: 'root',
141
- alwaysRedirect: true,
142
- },
143
- ...options.i18n,
144
- });
134
+ await installModule(
135
+ '@nuxtjs/i18n',
136
+ defu(options.i18n ?? {}, {
137
+ // NOSONAR
138
+ locales: [
139
+ { code: 'en', iso: 'en_US', file: 'en.json', name: 'English' },
140
+ { code: 'ms', iso: 'ms_MY', file: 'ms.json', name: 'Bahasa' },
141
+ ],
142
+ langDir,
143
+ defaultLocale: 'en',
144
+ strategy: 'no_prefix',
145
+ detectBrowserLanguage: {
146
+ useCookie: true,
147
+ cookieKey: 'dynect_language',
148
+ cookieSecure: true,
149
+ redirectOn: 'root',
150
+ alwaysRedirect: true,
151
+ },
152
+ })
153
+ );
145
154
  }
146
155
 
147
156
  if (options.icon !== false) {
148
- await installModule('@nuxt/icon', {
149
- provider: 'server',
150
- mode: 'svg',
151
- serverBundle: {
152
- collections: ['heroicons', 'lucide', 'mdi'],
153
- remote: false,
154
- },
155
- ...options.icon,
156
- });
157
+ await installModule(
158
+ '@nuxt/icon',
159
+ defu(options.icon ?? {}, {
160
+ // NOSONAR
161
+ provider: 'server',
162
+ mode: 'svg',
163
+ serverBundle: {
164
+ collections: ['heroicons', 'lucide', 'mdi'],
165
+ remote: false,
166
+ },
167
+ })
168
+ );
157
169
  }
158
170
 
159
- await installModule('@pinia/nuxt');
171
+ await installModule('@pinia/nuxt'); // NOSONAR
160
172
 
161
173
  // ── CSS ──────────────────────────────────────────────────────────────────
162
174
  const cssPath = isStandalone ? resolver.resolve('./runtime/assets/css/main.css') : resolver.resolve('../../../app/assets/css/main.css');
@@ -166,13 +178,13 @@ export default defineNuxtModule<DynectBaseOptions>({
166
178
  }
167
179
 
168
180
  // ── Components ───────────────────────────────────────────────────────────
169
- for (const dir of options.dirs!) {
181
+ for (const dir of options.dirs) {
170
182
  const dirPath = join(componentsBase, dir);
171
183
  if (!existsSync(dirPath)) continue;
172
184
 
173
185
  addComponentsDir({
174
186
  path: dirPath,
175
- prefix: DIR_CONFIGS[dir]!.prefix,
187
+ prefix: DIR_CONFIGS[dir].prefix,
176
188
  pathPrefix: false,
177
189
  global: options.global,
178
190
  });
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { toLowerCase } from '../../../utils/function';
3
- import { onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue';
3
+ import { onBeforeUnmount, onMounted, ref, shallowRef, useSlots, watch } from 'vue';
4
4
  import { OrgChart } from './main';
5
5
  import { SVG_ICONS, createIconSVG } from './svg-icons';
6
6
  import type { OrgChartNodeData, OrgChartNode } from './types';
@@ -107,7 +107,7 @@
107
107
  <script lang="ts"></script>
108
108
 
109
109
  <script lang="ts" setup>
110
- import { computed, nextTick, ref, watchEffect } from 'vue';
110
+ import { computed, nextTick, ref, useAttrs, watchEffect } from 'vue';
111
111
  import type { HeightT, Position, ToastT, ToastToDismiss, ToasterProps } from './types';
112
112
  import { ToastState } from './state';
113
113
  import Toast from './Toast.vue';
@@ -109,7 +109,7 @@
109
109
  <script setup lang="ts">
110
110
  import { capitalizeFirstLetter, countryList, toLowerCase, toUpperCase } from '../../utils/function';
111
111
  import { useField } from 'vee-validate';
112
- import { computed, nextTick, onMounted, reactive, readonly, ref, watch } from 'vue';
112
+ import { computed, nextTick, onMounted, reactive, readonly, ref, useTemplateRef, watch } from 'vue';
113
113
  import { parsePhoneNumberFromString, type CountryCode, type NumberFormat } from 'libphonenumber-js/max';
114
114
  import { cva } from 'class-variance-authority';
115
115
  import { useState, useId } from 'nuxt/app';