@fastkit/vui 0.8.18 → 0.10.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.
package/package.json CHANGED
@@ -1,11 +1,19 @@
1
1
  {
2
2
  "name": "@fastkit/vui",
3
- "version": "0.8.18",
4
- "description": "@fastkit/vui",
3
+ "version": "0.10.0",
4
+ "description": "A simple, extensible UI kit for Vue applications.",
5
5
  "buildOptions": {
6
6
  "name": "Vui",
7
7
  "tool": true
8
8
  },
9
+ "_docs": {
10
+ "scope": "vue",
11
+ "feature": "ui",
12
+ "description": {
13
+ "en": "A simple, extensible UI kit for Vue applications.",
14
+ "ja": "Vueアプリケーション用のシンプルで拡張可能なUIキット。"
15
+ }
16
+ },
9
17
  "main": "index.js",
10
18
  "module": "dist/vui.mjs",
11
19
  "files": [
@@ -19,7 +27,10 @@
19
27
  "url": "git+https://github.com/dadajam4/fastkit.git"
20
28
  },
21
29
  "keywords": [
22
- "fastkit"
30
+ "fastkit",
31
+ "vue",
32
+ "ui",
33
+ "component"
23
34
  ],
24
35
  "author": "dadajam4",
25
36
  "license": "MIT",
@@ -28,21 +39,31 @@
28
39
  },
29
40
  "homepage": "https://github.com/dadajam4/fastkit/tree/dev/packages/vui#readme",
30
41
  "peerDependencies": {
31
- "vite": "^2.9.13",
32
- "vue": "^3.2.37"
42
+ "vite": "^4.0.4",
43
+ "vue": "^3.2.45"
33
44
  },
34
45
  "dependencies": {
35
- "@fastkit/color-scheme": "0.8.18",
36
- "@fastkit/icon-font": "0.8.18",
37
- "@fastkit/tiny-logger": "0.8.18",
38
- "@fastkit/vite-kit": "0.8.18",
39
- "@fastkit/vue-kit": "0.8.18",
40
- "@tiptap/extension-link": "^2.0.0-beta.43",
41
- "@tiptap/extension-underline": "^2.0.0-beta.25",
42
- "@tiptap/extension-text-style": "^2.0.0-beta.26",
43
- "@tiptap/starter-kit": "^2.0.0-beta.191",
44
- "@tiptap/vue-3": "^2.0.0-beta.96",
46
+ "@fastkit/color-scheme": "0.10.0",
47
+ "@fastkit/icon-font": "0.10.0",
48
+ "@fastkit/tiny-logger": "0.10.0",
49
+ "@fastkit/vite-kit": "0.10.0",
50
+ "@fastkit/vue-kit": "0.10.0",
51
+ "@tiptap/extension-link": "^2.0.0-beta.209",
52
+ "@tiptap/extension-text-style": "^2.0.0-beta.209",
53
+ "@tiptap/extension-underline": "^2.0.0-beta.209",
54
+ "@tiptap/starter-kit": "^2.0.0-beta.209",
55
+ "@tiptap/vue-3": "^2.0.0-beta.209",
45
56
  "eta": "^1.12.3",
46
- "fs-extra": "^9.1.0"
57
+ "fs-extra": "^11.1.0",
58
+ "prosemirror-commands": "^1.5.0",
59
+ "prosemirror-dropcursor": "^1.6.1",
60
+ "prosemirror-gapcursor": "^1.3.1",
61
+ "prosemirror-history": "^1.3.0",
62
+ "prosemirror-keymap": "^1.2.0",
63
+ "prosemirror-model": "^1.18.3",
64
+ "prosemirror-schema-list": "^1.2.2",
65
+ "prosemirror-state": "^1.4.2",
66
+ "prosemirror-transform": "^1.7.0",
67
+ "prosemirror-view": "^1.29.1"
47
68
  }
48
69
  }
@@ -45,7 +45,7 @@ export const VBreadcrumbs = defineComponent({
45
45
  return items.map((item) => {
46
46
  const { to, text } = item;
47
47
  const {
48
- disabled = vui.location.match(to) || !vui.location.isAvairable(to),
48
+ disabled = vui.location.match(to) || !vui.location.isAvailable(to),
49
49
  } = item;
50
50
  return {
51
51
  ...item,
@@ -96,7 +96,7 @@ export const VBusyImage = defineComponent({
96
96
  },
97
97
  setup(props, ctx) {
98
98
  const loadStateRef = ref<BusyImageLoadState>(
99
- props.cover && isAvairableSrc(ctx.attrs.src as any)
99
+ props.cover && isAvailableSrc(ctx.attrs.src as any)
100
100
  ? 'loading'
101
101
  : 'pending',
102
102
  );
@@ -173,7 +173,7 @@ export const VBusyImage = defineComponent({
173
173
  () => ctx.attrs.src as string | null | undefined,
174
174
  (value) => {
175
175
  coverImageRef.value = undefined;
176
- if (isAvairableSrc(value)) {
176
+ if (isAvailableSrc(value)) {
177
177
  loadStateRef.value = 'loading';
178
178
  if (props.cover) {
179
179
  loadImage(value)
@@ -273,6 +273,6 @@ function imageIsReady(image: HTMLImageElement): 'load' | 'error' | false {
273
273
  return image.naturalWidth + image.naturalHeight > 0 ? 'load' : 'error';
274
274
  }
275
275
 
276
- function isAvairableSrc(src: string | null | undefined): src is string {
276
+ function isAvailableSrc(src: string | null | undefined): src is string {
277
277
  return typeof src === 'string' && src !== '';
278
278
  }
@@ -38,6 +38,14 @@
38
38
  transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1), color 1ms;
39
39
  appearance: none;
40
40
 
41
+ &--align-left {
42
+ justify-content: flex-start;
43
+ }
44
+
45
+ &--align-right {
46
+ justify-content: flex-end;
47
+ }
48
+
41
49
  &--plain {
42
50
  color: inherit !important;
43
51
  // color: inherit !important;
@@ -30,6 +30,10 @@ export type VButtonIcon = () => VNodeChild;
30
30
 
31
31
  export type RawVButtonIcon = IconName | VButtonIcon;
32
32
 
33
+ export const BUTTON_ALIGNS = ['left', 'center', 'right'] as const;
34
+
35
+ export type VButtonAlign = typeof BUTTON_ALIGNS[number];
36
+
33
37
  function resolveRawVButtonIcon(
34
38
  raw?: RawVButtonIcon,
35
39
  type: 'main' | 'start' | 'end' = 'main',
@@ -54,6 +58,10 @@ export const vueButtonProps = createPropsOptions({
54
58
  icon: [String, Function] as PropType<RawVButtonIcon>,
55
59
  startIcon: [String, Function] as PropType<RawVButtonIcon>,
56
60
  endIcon: [String, Function] as PropType<RawVButtonIcon>,
61
+ align: {
62
+ type: String as PropType<VButtonAlign>,
63
+ default: 'center',
64
+ },
57
65
  ...createControlProps(),
58
66
  });
59
67
 
@@ -115,6 +123,7 @@ export const VButton = defineComponent({
115
123
  // navigationable.value.classes,
116
124
  spacer.value ? `v-button--spacer-${spacer.value}` : undefined,
117
125
  `v-button--${control.size.value}`,
126
+ `v-button--align-${props.align}`,
118
127
  {
119
128
  'v-button--loading': isLoading.value,
120
129
  'v-button--icon': !!icon.value,
@@ -401,7 +401,11 @@ export const VDataTable = defineComponent({
401
401
 
402
402
  vui.location.pushQuery({
403
403
  ...queries,
404
- [props.pageQuery]: 1,
404
+ ...(usePaigingRef.value
405
+ ? {
406
+ [props.pageQuery]: 1,
407
+ }
408
+ : undefined),
405
409
  });
406
410
  }
407
411
 
@@ -530,7 +534,7 @@ export const VDataTable = defineComponent({
530
534
  const isIndeterminate = isIndeterminateRef.value;
531
535
  const isAllSelected = isAllSelectedRef.value;
532
536
  const { defaultOrder, ascQueryValue } = props;
533
- const usePaiging = usePaigingRef.value;
537
+ // const usePaiging = usePaigingRef.value;
534
538
 
535
539
  const children = headersRef.value.map((header) => {
536
540
  const { label, sortQuery, align, key } = header;
@@ -567,7 +571,7 @@ export const VDataTable = defineComponent({
567
571
 
568
572
  const sortActive = sortBy === sortQuery;
569
573
 
570
- if (sortQuery && usePaiging) {
574
+ if (sortQuery) {
571
575
  const isASC = sortActive
572
576
  ? isASCRef.value
573
577
  : defaultOrder === ascQueryValue;
@@ -615,9 +619,9 @@ export const VDataTable = defineComponent({
615
619
  <th
616
620
  class={classes}
617
621
  key={header.key}
618
- tabindex={sortQuery && usePaiging ? 0 : undefined}
622
+ tabindex={sortQuery ? 0 : undefined}
619
623
  onClick={(ev) => {
620
- if (!sortQuery || !usePaiging) return;
624
+ if (!sortQuery) return;
621
625
  handleClickSortHeader(header, ev);
622
626
  }}>
623
627
  <div class="v-data-table__table__cell__tile">{headerChildren}</div>
@@ -14,8 +14,9 @@ import {
14
14
  createPropsOptions,
15
15
  } from '@fastkit/vue-utils';
16
16
  import { useScopeColorClass, ScopeName } from '@fastkit/vue-color-scheme';
17
- import { useLink } from 'vue-router';
17
+ // import { useLink } from 'vue-router';
18
18
  import { VLink } from '@fastkit/vue-utils';
19
+ import { useVui } from '../../injections';
19
20
 
20
21
  export function createListTileProps() {
21
22
  const icon = rawIconProp();
@@ -47,6 +48,7 @@ export const VListTile = defineComponent({
47
48
  ...listTileEmits,
48
49
  },
49
50
  setup(props, ctx) {
51
+ const vui = useVui();
50
52
  const startIcon: ComputedRef<VNodeChild> = computed(() => {
51
53
  let icon = resolveRawIconProp(false, props.startIcon);
52
54
  if (!icon && props.startIconEmptySpace) {
@@ -60,7 +62,7 @@ export const VListTile = defineComponent({
60
62
 
61
63
  const hasTo = computed(() => !!ctx.attrs.to);
62
64
 
63
- const link = useLink({ to: (ctx.attrs.to as any) || '' });
65
+ const link = vui.useLink({ to: (ctx.attrs.to as any) || '' });
64
66
 
65
67
  const isActive = computed(() => {
66
68
  if (!hasTo.value) return false;
@@ -12,10 +12,10 @@ import {
12
12
  renderNavigationItemInput,
13
13
  } from './VNavigationItem';
14
14
  import { useScopeColorClass, ScopeName } from '@fastkit/vue-color-scheme';
15
+ import { createPropsOptions, ExtractPropInput } from '@fastkit/vue-utils';
15
16
 
16
- export const VNavigation = defineComponent({
17
- name: 'VNavigation',
18
- props: {
17
+ export function createNavigationProps() {
18
+ return createPropsOptions({
19
19
  items: {
20
20
  type: Array as PropType<NavigationItemInput[]>,
21
21
  required: true,
@@ -26,7 +26,16 @@ export const VNavigation = defineComponent({
26
26
  default: true,
27
27
  },
28
28
  caption: [String, Function] as PropType<VNodeChild | (() => VNodeChild)>,
29
- },
29
+ });
30
+ }
31
+
32
+ export type NavigationInput = ExtractPropInput<
33
+ ReturnType<typeof createNavigationProps>
34
+ >;
35
+
36
+ export const VNavigation = defineComponent({
37
+ name: 'VNavigation',
38
+ props: createNavigationProps(),
30
39
  setup(props, ctx) {
31
40
  const items = computed(() => props.items);
32
41
  const color = useScopeColorClass(props);
@@ -22,7 +22,7 @@ import { ScopeName } from '@fastkit/color-scheme';
22
22
  export function createNavigationItemProps() {
23
23
  return {
24
24
  ...createListTileProps(),
25
- match: String,
25
+ match: [String, Array] as PropType<string | string[]>,
26
26
  depth: {
27
27
  type: Number,
28
28
  default: 0,
@@ -72,6 +72,12 @@ export function renderNavigationItemInput(
72
72
  );
73
73
  }
74
74
 
75
+ const TRIM_END_SLASH_RE = /\/$/;
76
+
77
+ function trimEndSlash<T extends string | undefined>(sorce: T) {
78
+ return sorce ? sorce.replace(TRIM_END_SLASH_RE, '') : sorce;
79
+ }
80
+
75
81
  export const VNavigationItem = defineComponent({
76
82
  name: 'VNavigationItem',
77
83
  inheritAttrs: false,
@@ -93,13 +99,16 @@ export const VNavigationItem = defineComponent({
93
99
 
94
100
  const to = computed(() => ctx.attrs.to);
95
101
 
96
- const match = computed(() => {
102
+ const match = computed<string[] | undefined>(() => {
97
103
  const { match } = props;
98
104
  const { to } = ctx.attrs;
99
- if (match) return match;
105
+ if (match) {
106
+ return (Array.isArray(match) ? match : [match]).map(trimEndSlash);
107
+ }
100
108
  if (!to) return;
101
- if (typeof to === 'string') return to;
102
- return (to as any).path as string | undefined;
109
+ const toPath = typeof to === 'string' ? to : (to as any).path;
110
+ if (!toPath) return;
111
+ return [trimEndSlash(toPath)];
103
112
  });
104
113
 
105
114
  const classes = computed(() => [
@@ -123,18 +132,27 @@ export const VNavigationItem = defineComponent({
123
132
  const c = children.value;
124
133
  const m = match.value;
125
134
 
126
- if (!c || !m) {
135
+ if (!c || !m || !m.length) {
127
136
  // matched.value = false;
128
137
  return;
129
138
  }
130
139
 
131
- if (newPath.match(m)) {
140
+ const trimedNewPath = trimEndSlash(newPath);
141
+ if (m.some((_) => trimedNewPath.match(_))) {
132
142
  open();
133
143
  // matched.value = true;
134
144
  } else {
135
145
  close();
136
146
  // matched.value = false;
137
147
  }
148
+
149
+ // if (trimEndSlash(newPath).match(m)) {
150
+ // open();
151
+ // // matched.value = true;
152
+ // } else {
153
+ // close();
154
+ // // matched.value = false;
155
+ // }
138
156
  },
139
157
  { immediate: true },
140
158
  );
@@ -18,7 +18,7 @@ import {
18
18
  createPropsOptions,
19
19
  VNodeChildOrSlot,
20
20
  resolveVNodeChildOrSlots,
21
- useKeybord,
21
+ useKeyboard,
22
22
  } from '@fastkit/vue-kit';
23
23
  import { VFormControl } from '../VFormControl';
24
24
  import {
@@ -40,11 +40,11 @@ import { VOption } from '../VOption';
40
40
  import { VButton } from '..';
41
41
  import { VMenuControl } from '@fastkit/vue-stack';
42
42
 
43
- export const ARROW_KEY_TYPES = useKeybord.Key(['ArrowUp', 'ArrowDown']);
43
+ export const ARROW_KEY_TYPES = useKeyboard.Key(['ArrowUp', 'ArrowDown']);
44
44
 
45
- export const CHOICE_KEY_TYPES = useKeybord.Key(['Enter', ' ']);
45
+ export const CHOICE_KEY_TYPES = useKeyboard.Key(['Enter', ' ']);
46
46
 
47
- export const KEYBORD_EVENT_TYPES = useKeybord.Key([
47
+ export const KEYBORD_EVENT_TYPES = useKeyboard.Key([
48
48
  ...ARROW_KEY_TYPES,
49
49
  ...CHOICE_KEY_TYPES,
50
50
  ]);
@@ -59,12 +59,18 @@ export const VSelect = defineComponent({
59
59
  ...createControlFieldProps(),
60
60
  ...createControlFieldProviderProps(),
61
61
  ...createControlProps(),
62
- ...defineSlotsProps<FormControlSlots & InputBoxSlots>(),
62
+ ...defineSlotsProps<
63
+ FormControlSlots &
64
+ InputBoxSlots & {
65
+ selection: { item: FormSelectorItemControl; index: number };
66
+ }
67
+ >(),
63
68
  ...createPropsOptions({
64
69
  placeholder: String,
65
70
  loadingMessage: {} as PropType<VNodeChildOrSlot>,
66
71
  failedToLoadItemsMessage: {} as PropType<VNodeChildOrSlot>,
67
72
  }),
73
+ closeOnNavigation: Boolean,
68
74
  },
69
75
  emits,
70
76
  setup(props, ctx) {
@@ -109,6 +115,7 @@ export const VSelect = defineComponent({
109
115
  };
110
116
 
111
117
  const renderSelections = (selectedItems: FormSelectorItemControl[]) => {
118
+ const selectionSlot = ctx.slots.selection;
112
119
  const children: VNodeChild[] = [];
113
120
  if (inputControl.itemsLoadFailed) {
114
121
  children.push(
@@ -125,7 +132,10 @@ export const VSelect = defineComponent({
125
132
  if (index > 0) {
126
133
  children.push(vui.selectionSeparator());
127
134
  }
128
- children.push(item.renderDefaultSlot());
135
+ const child = selectionSlot
136
+ ? selectionSlot({ item, index })
137
+ : item.renderDefaultSlot();
138
+ children.push(child);
129
139
  });
130
140
  } else if (props.placeholder != null) {
131
141
  children.push(
@@ -239,16 +249,16 @@ export const VSelect = defineComponent({
239
249
  }
240
250
  };
241
251
 
242
- const keybordEventHandler = (ev: KeyboardEvent) => {
252
+ const keyboardEventHandler = (ev: KeyboardEvent) => {
243
253
  if (ARROW_KEY_TYPES.includes(ev.key as any)) return arrowKeyHandler(ev);
244
254
  if (CHOICE_KEY_TYPES.includes(ev.key as any)) return choiceKeyHandler(ev);
245
255
  };
246
256
 
247
- useKeybord(
257
+ useKeyboard(
248
258
  [
249
259
  {
250
260
  key: KEYBORD_EVENT_TYPES,
251
- handler: keybordEventHandler,
261
+ handler: keyboardEventHandler,
252
262
  },
253
263
  ],
254
264
  { autorun: true },
@@ -317,6 +327,7 @@ export const VSelect = defineComponent({
317
327
  <VMenu
318
328
  width="fit"
319
329
  maxWidth="fit"
330
+ closeOnNavigation={this.closeOnNavigation}
320
331
  distance={0}
321
332
  alwaysRender
322
333
  v-model={this.menuOpened}
@@ -39,7 +39,7 @@ import {
39
39
  BubbleMenu,
40
40
  FocusPosition,
41
41
  } from '@tiptap/vue-3';
42
- import StarterKit from '@tiptap/starter-kit';
42
+ import { StarterKit } from '@tiptap/starter-kit';
43
43
  import { VButton, VButtonGroup } from '../VButton';
44
44
  import {
45
45
  RawWysiwygExtension,
package/src/plugin.tsx CHANGED
@@ -83,7 +83,7 @@ export class VuiPlugin {
83
83
  app.config.globalProperties.$vui = $vui;
84
84
 
85
85
  onAppUnmount(app, () => {
86
- delete app.config.globalProperties.$vui;
86
+ delete (app.config.globalProperties as any).$vui;
87
87
  });
88
88
  }
89
89
  }
package/src/service.tsx CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  resolveVStackDynamicInput,
13
13
  } from '@fastkit/vue-kit';
14
14
  import type { Router } from 'vue-router';
15
- import { RouterLink } from 'vue-router';
15
+ import { RouterLink, useLink, UseLinkOptions } from 'vue-router';
16
16
  import { LocationService, setDefaultRouterLink } from '@fastkit/vue-utils';
17
17
  import { VForm } from './components/VForm';
18
18
  import { VTextField, TextFieldInput } from './components/VTextField';
@@ -20,6 +20,8 @@ import { VueForm, FormControlHinttipDelay } from '@fastkit/vue-form-control';
20
20
  import { getDocumentScroller } from '@fastkit/vue-scroller';
21
21
  import { ControlSize } from './schemes';
22
22
 
23
+ export type UseLinkResult = ReturnType<typeof useLink>;
24
+
23
25
  export interface VuiFormPromptSettings<
24
26
  T extends { [key: string]: any } = { [key: string]: any },
25
27
  > extends Partial<VDialogProps> {
@@ -133,7 +135,8 @@ export type VuiVNodeResolver = () => VNodeChild;
133
135
 
134
136
  export interface VuiServiceOptions {
135
137
  router: Router;
136
- RouterLink?: typeof RouterLink;
138
+ RouterLink?: any;
139
+ useLink?: (props: UseLinkOptions) => UseLinkResult;
137
140
  colorScheme: VueColorSchemePluginSettings;
138
141
  uiSettings: VuiServiceUISettings;
139
142
  icons: VuiServiceIconSettings;
@@ -183,6 +186,7 @@ export class VuiService {
183
186
  readonly router: Router;
184
187
  readonly location: LocationService;
185
188
  readonly stack: VueStackService;
189
+ readonly useLink: typeof useLink;
186
190
 
187
191
  get scroller() {
188
192
  return getDocumentScroller();
@@ -207,6 +211,7 @@ export class VuiService {
207
211
  router: this.router,
208
212
  });
209
213
  this.stack = stackService;
214
+ this.useLink = options.useLink || useLink;
210
215
  }
211
216
 
212
217
  configure(options?: Partial<VuiServiceOptions>) {
@@ -23,7 +23,7 @@
23
23
 
24
24
  @mixin elevation($z, $important: false) {
25
25
  box-shadow: var(--shadow-key-umbra-#{$z}), var(--shadow-key-penumbra-#{$z}),
26
- var(--shadow-key-ambient-#{$z}) if($important, !important, null);
26
+ var(--shadow-key-ambient-#{$z}) if($important, unquote('!important'), null);
27
27
  }
28
28
 
29
29
  @mixin elevation-transition(