@fastkit/vui 0.7.44 → 0.7.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/vui.cjs.js CHANGED
@@ -9,8 +9,8 @@ var vueUtils = require('@fastkit/vue-utils');
9
9
  var vueScroller = require('@fastkit/vue-scroller');
10
10
  var vueColorScheme = require('@fastkit/vue-color-scheme');
11
11
  var vueLoading = require('@fastkit/vue-loading');
12
- var iconFont = require('@fastkit/icon-font');
13
12
  var helpers = require('@fastkit/helpers');
13
+ var iconFont = require('@fastkit/icon-font');
14
14
  var vueAppLayout = require('@fastkit/vue-app-layout');
15
15
  var vueFormControl = require('@fastkit/vue-form-control');
16
16
  var vue3 = require('@tiptap/vue-3');
@@ -292,7 +292,7 @@ const VFormControl = vue.defineComponent({
292
292
  ctx.emit('clickLabel', ev, control);
293
293
  }
294
294
  }, [label, getRequiredChip(), hinttip && vue.createVNode(vueKit.VTooltip, {
295
- "top": true,
295
+ "y": "top",
296
296
  "openOnHover": _hinttipDelay !== 'click',
297
297
  "openDelay": typeof _hinttipDelay === 'number' ? _hinttipDelay : undefined
298
298
  }, {
@@ -355,6 +355,9 @@ function defineFormSelectorComponent(opts) {
355
355
  },
356
356
 
357
357
  render() {
358
+ const {
359
+ selectorControl
360
+ } = this;
358
361
  return vue.createVNode(VFormControl, {
359
362
  "nodeControl": this.nodeControl,
360
363
  "focused": this.nodeControl.focused,
@@ -369,14 +372,20 @@ function defineFormSelectorComponent(opts) {
369
372
  }, { ...this.$slots,
370
373
  default: () => vue.createVNode("div", {
371
374
  "class": "v-form-selector__body"
372
- }, [this.propItems.map(attrs => itemRenderer({
373
- attrs: { ...attrs,
374
- key: attrs.value
375
- },
376
- slots: {
377
- default: () => attrs.label(this.selectorControl)
378
- }
379
- })), vueKit.renderSlotOrEmpty(this.$slots, 'default')])
375
+ }, [this.propItems.map(attrs => {
376
+ const selected = selectorControl.isSelected(attrs.value);
377
+ return itemRenderer({
378
+ selected,
379
+ control: selectorControl,
380
+ attrs: { ...attrs,
381
+ modelValue: selected,
382
+ key: attrs.value
383
+ },
384
+ slots: {
385
+ default: () => attrs.label(this.selectorControl)
386
+ }
387
+ });
388
+ }), vueKit.renderSlotOrEmpty(this.$slots, 'default')])
380
389
  });
381
390
  }
382
391
 
@@ -400,6 +409,248 @@ function useElevation(props, opts = {}) {
400
409
  };
401
410
  }
402
411
 
412
+ function _isSlot$e(s) {
413
+ return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !vue.isVNode(s);
414
+ }
415
+
416
+ const VSkeltonLoaderBone = vue.defineComponent({
417
+ name: 'VSkeltonLoaderBone',
418
+ inheritAttrs: false,
419
+ props: {
420
+ tag: {
421
+ type: String,
422
+ default: 'div'
423
+ }
424
+ },
425
+
426
+ setup(props, ctx) {
427
+ return () => {
428
+ let _slot;
429
+
430
+ const TagName = props.tag;
431
+ return vue.createVNode(TagName, vue.mergeProps(ctx.attrs, {
432
+ "class": "v-skelton-loader-bone"
433
+ }), _isSlot$e(_slot = vueUtils.renderSlotOrEmpty(ctx.slots)) ? _slot : {
434
+ default: () => [_slot]
435
+ });
436
+ };
437
+ }
438
+
439
+ });
440
+
441
+ const IMAGE_ATTRS = ['alt', 'crossorigin', 'decoding', 'sizes', 'src', 'srcset', 'usemap'];
442
+ function splitAttrs(attrs) {
443
+ const el = { ...attrs
444
+ };
445
+ const img = {};
446
+
447
+ for (const ATTR of IMAGE_ATTRS) {
448
+ const value = attrs[ATTR];
449
+
450
+ if (value != null) {
451
+ img[ATTR] = value;
452
+ }
453
+ }
454
+
455
+ return {
456
+ el,
457
+ img
458
+ };
459
+ }
460
+ const NUMBERISH_PROP = [Number, String];
461
+ const DEFAULT_HEIGHT = 150;
462
+
463
+ const resolveBusyImageSizeValue = source => {
464
+ if (source == null) return;
465
+ return isNaN(source) ? String(source) : `${source}px`;
466
+ };
467
+ /**
468
+ * 画像表示用コンポーネント
469
+ * <img /> タグのように振る舞うが、ローディング表示や、表示サイズの調整など、ちょっといい感じにやるためのコンポーネント
470
+ */
471
+
472
+
473
+ const VBusyImage = vue.defineComponent({
474
+ name: 'VBusyImage',
475
+ props: { ...undefined,
476
+ aspectRatio: String,
477
+ width: NUMBERISH_PROP,
478
+ height: NUMBERISH_PROP,
479
+ cover: Boolean,
480
+ ...vueUtils.defineSlotsProps()
481
+ },
482
+ emits: {
483
+ load: ev => true,
484
+ error: ev => true
485
+ },
486
+
487
+ setup(props, ctx) {
488
+ const loadStateRef = vue.ref(props.cover && isAvairableSrc(ctx.attrs.src) ? 'loading' : 'pending');
489
+ const attrsRef = vue.computed(() => splitAttrs(ctx.attrs));
490
+ const isPendingRef = vue.computed(() => loadStateRef.value === 'pending');
491
+ const isLoadingRef = vue.computed(() => loadStateRef.value === 'loading');
492
+ const isLoadedRef = vue.computed(() => loadStateRef.value === 'loaded');
493
+ const isErrorRef = vue.computed(() => loadStateRef.value === 'error');
494
+ const classesRef = vue.computed(() => [`v-busy-image--${loadStateRef.value}`, {
495
+ 'v-busy-image--cover': props.cover,
496
+ 'v-busy-image--clickable': typeof ctx.attrs.onClick === 'function'
497
+ }]);
498
+ const nodeRef = vue.ref();
499
+ const coverImageRef = vue.ref();
500
+ const rectsRef = vue.computed(() => {
501
+ const placeholder = {};
502
+ const main = {};
503
+ const {
504
+ cover
505
+ } = props;
506
+ let {
507
+ width,
508
+ height
509
+ } = props;
510
+
511
+ if (height == null && cover) {
512
+ height = DEFAULT_HEIGHT;
513
+ }
514
+
515
+ if (width == null && cover) {
516
+ width = height;
517
+ }
518
+
519
+ width = resolveBusyImageSizeValue(width);
520
+ height = resolveBusyImageSizeValue(height);
521
+ main.width = width;
522
+ main.height = height;
523
+ placeholder.width = width;
524
+ placeholder.height = height;
525
+
526
+ if (placeholder.height == null) {
527
+ placeholder.height = resolveBusyImageSizeValue(DEFAULT_HEIGHT);
528
+ }
529
+
530
+ if (placeholder.width == null) {
531
+ placeholder.width = placeholder.height;
532
+ }
533
+
534
+ return {
535
+ placeholder,
536
+ main
537
+ };
538
+ });
539
+ const currentRectRef = vue.computed(() => isLoadedRef.value ? rectsRef.value.main : rectsRef.value.placeholder);
540
+ const stylesRef = vue.computed(() => {
541
+ const {
542
+ value: coverImage
543
+ } = coverImageRef;
544
+ const coverSrc = coverImage && coverImage.src;
545
+ const styles = { ...currentRectRef.value
546
+ };
547
+
548
+ if (coverSrc) {
549
+ styles.backgroundImage = `url(${coverSrc})`;
550
+ }
551
+
552
+ return styles;
553
+ });
554
+ let booted = false;
555
+ vue.watch(() => ctx.attrs.src, value => {
556
+ coverImageRef.value = undefined;
557
+
558
+ if (isAvairableSrc(value)) {
559
+ loadStateRef.value = 'loading';
560
+
561
+ if (props.cover) {
562
+ helpers.loadImage(value).then(image => {
563
+ coverImageRef.value = image;
564
+ setManualState('load');
565
+ }).catch(err => {
566
+ setManualState('error');
567
+ });
568
+ }
569
+ } else {
570
+ loadStateRef.value = 'pending';
571
+ }
572
+ }, {
573
+ immediate: helpers.IN_WINDOW
574
+ });
575
+
576
+ const setManualState = loadType => {
577
+ loadStateRef.value = loadType === 'load' ? 'loaded' : 'error';
578
+ const ev = new Event(loadType, {
579
+ bubbles: false,
580
+ cancelable: false,
581
+ composed: false
582
+ });
583
+ ctx.emit(loadType, ev);
584
+ };
585
+
586
+ vue.onMounted(() => {
587
+ if (booted || props.cover) return;
588
+ const image = nodeRef.value;
589
+ if (!image) return;
590
+ const loadType = imageIsReady(image);
591
+
592
+ if (loadType) {
593
+ setManualState(loadType);
594
+ }
595
+ });
596
+ vue.onBeforeUnmount(() => {
597
+ coverImageRef.value = undefined;
598
+ });
599
+
600
+ const handleLoad = ev => {
601
+ booted = true;
602
+ loadStateRef.value = 'loaded';
603
+ ctx.emit('load', ev);
604
+ };
605
+
606
+ const handleError = ev => {
607
+ booted = true;
608
+ loadStateRef.value = 'error';
609
+ ctx.emit('error', ev);
610
+ };
611
+
612
+ ctx.expose({
613
+ state: loadStateRef,
614
+ isPending: isPendingRef,
615
+ isLoading: isLoadingRef,
616
+ isLoaded: isLoadedRef,
617
+ isError: isErrorRef
618
+ });
619
+ return () => {
620
+ const {
621
+ el: elAttrs,
622
+ img: imgAttrs
623
+ } = attrsRef.value;
624
+ const styles = stylesRef.value;
625
+ const children = ctx.slots.default && ctx.slots.default();
626
+ return vue.createVNode("span", vue.mergeProps({
627
+ "class": ['v-busy-image', classesRef.value]
628
+ }, elAttrs, {
629
+ "style": styles
630
+ }), [!props.cover && vue.createVNode("img", vue.mergeProps({
631
+ "key": "img",
632
+ "ref": nodeRef,
633
+ "class": "v-busy-image__node"
634
+ }, imgAttrs, {
635
+ "onLoad": handleLoad,
636
+ "onError": handleError
637
+ }), null), !!children && vue.createVNode("span", {
638
+ "class": "v-busy-image__slot"
639
+ }, [children])]);
640
+ };
641
+ }
642
+
643
+ });
644
+
645
+ function imageIsReady(image) {
646
+ if (!image.complete) return false;
647
+ return image.naturalWidth + image.naturalHeight > 0 ? 'load' : 'error';
648
+ }
649
+
650
+ function isAvairableSrc(src) {
651
+ return typeof src === 'string' && src !== '';
652
+ }
653
+
403
654
  function extractRawGridValueClasses(value, prefix, getter) {
404
655
  if (typeof value !== 'object')
405
656
  return `${prefix}${getter ? getter(value) : value}`;
@@ -625,6 +876,162 @@ const VPaper = vue.defineComponent({
625
876
 
626
877
  });
627
878
 
879
+ const AVATAR_SIZES = ['sm', 'md', 'lg'];
880
+ function createAvatarProps() {
881
+ return { ...vueColorScheme.colorSchemeProps(),
882
+ ...vueUtils.navigationableInheritProps,
883
+ size: {
884
+ type: [String, Number],
885
+ default: 'md'
886
+ },
887
+ tile: Boolean,
888
+ rounded: Boolean,
889
+ disabled: Boolean,
890
+ src: String
891
+ };
892
+ }
893
+ const VAvatar = vue.defineComponent({
894
+ name: 'VAvatar',
895
+ inheritAttrs: false,
896
+ props: createAvatarProps(),
897
+
898
+ setup(props, ctx) {
899
+ const vui = useVui();
900
+ const defaults = vui.setting('buttonDefault');
901
+ const color = vueColorScheme.useColorClasses({
902
+ color: () => props.color || defaults.color,
903
+ variant: () => props.variant || defaults.variant
904
+ });
905
+ const navigationable = vueUtils.useNavigationable(ctx, {
906
+ clickableClassName: () => 'v-avatar--clickable',
907
+ linkFallbackTag: 'div'
908
+ });
909
+ const classes = vue.computed(() => {
910
+ const {
911
+ size
912
+ } = props;
913
+ return [{
914
+ 'v-avatar--tile': props.tile,
915
+ 'v-avatar--rounded': props.rounded
916
+ }, typeof size === 'string' && `v-avatar--${size}`];
917
+ });
918
+ const styles = vue.computed(() => {
919
+ const {
920
+ size
921
+ } = props;
922
+ if (typeof size !== 'number') return;
923
+ return {
924
+ '--avatar-size': `${size}px`
925
+ };
926
+ });
927
+ return () => {
928
+ const {
929
+ src
930
+ } = props;
931
+ const {
932
+ Tag,
933
+ attrs
934
+ } = navigationable.value;
935
+ return vue.createVNode(Tag, vue.mergeProps(attrs, {
936
+ "class": ['v-avatar', classes.value, color.colorClasses.value],
937
+ "style": styles.value
938
+ }), {
939
+ default: () => [!!src && vue.createVNode(VBusyImage, {
940
+ "class": "v-avatar__image",
941
+ "src": src,
942
+ "cover": true
943
+ }, null) || vueUtils.renderSlotOrEmpty(ctx.slots)]
944
+ });
945
+ };
946
+ }
947
+
948
+ });
949
+
950
+ const CHIP_SIZES = ['xs', 'sm', 'md', 'lg', 'xl'];
951
+ function createChipProps() {
952
+ return { ...vueColorScheme.colorSchemeProps(),
953
+ ...vueUtils.navigationableInheritProps,
954
+ size: {
955
+ type: String,
956
+ default: 'md'
957
+ },
958
+ startIcon: [String, Function],
959
+ endIcon: [String, Function],
960
+ label: Boolean,
961
+ disabled: Boolean
962
+ };
963
+ }
964
+
965
+ function resolveRawVChipIcon(raw, type) {
966
+ if (!raw) return;
967
+
968
+ if (typeof raw === 'function') {
969
+ return () => {
970
+ const child = raw();
971
+ if (child == null) return;
972
+ return vue.createVNode("span", {
973
+ "class": ['v-chip__icon', `v-chip__icon--${type}`]
974
+ }, [child]);
975
+ };
976
+ }
977
+
978
+ return () => vue.createVNode(VIcon, {
979
+ "class": ['v-chip__icon', `v-chip__icon--${type}`],
980
+ "name": raw
981
+ }, null);
982
+ }
983
+
984
+ const VChip = vue.defineComponent({
985
+ name: 'VChip',
986
+ inheritAttrs: false,
987
+ props: createChipProps(),
988
+
989
+ setup(props, ctx) {
990
+ const vui = useVui();
991
+ const defaults = vui.setting('buttonDefault');
992
+ const color = vueColorScheme.useColorClasses({
993
+ color: () => props.color || defaults.color,
994
+ variant: () => props.variant || defaults.variant
995
+ });
996
+ const startIcon = vue.computed(() => {
997
+ const _icon = resolveRawVChipIcon(props.startIcon, 'start');
998
+
999
+ return _icon && _icon();
1000
+ });
1001
+ const endIcon = vue.computed(() => {
1002
+ const _icon = resolveRawVChipIcon(props.endIcon, 'end');
1003
+
1004
+ return _icon && _icon();
1005
+ });
1006
+ const navigationable = vueUtils.useNavigationable(ctx, {
1007
+ clickableClassName: () => 'v-chip--clickable',
1008
+ linkFallbackTag: 'div'
1009
+ });
1010
+ const classes = vue.computed(() => {
1011
+ const {
1012
+ size
1013
+ } = props;
1014
+ return [{
1015
+ 'v-chip--label': props.label
1016
+ }, typeof size === 'string' && `v-chip--${size}`];
1017
+ });
1018
+ return () => {
1019
+ const {
1020
+ Tag,
1021
+ attrs
1022
+ } = navigationable.value;
1023
+ return vue.createVNode(Tag, vue.mergeProps(attrs, {
1024
+ "class": ['v-chip', classes.value, color.colorClasses.value]
1025
+ }), {
1026
+ default: () => [startIcon.value, vue.createVNode("span", {
1027
+ "class": "v-chip__content"
1028
+ }, [vueUtils.renderSlotOrEmpty(ctx.slots)]), endIcon.value]
1029
+ });
1030
+ };
1031
+ }
1032
+
1033
+ });
1034
+
628
1035
  function createCardProps() {
629
1036
  return { ...createPaperProps(),
630
1037
  ...vueUtils.navigationableInheritProps,
@@ -4511,11 +4918,15 @@ exports.VMenu = vueKit.VMenu;
4511
4918
  exports.VSnackbar = vueKit.VSnackbar;
4512
4919
  exports.VTooltip = vueKit.VTooltip;
4513
4920
  exports.ICON_NAMES = iconFont.ICON_NAMES;
4921
+ exports.AVATAR_SIZES = AVATAR_SIZES;
4922
+ exports.CHIP_SIZES = CHIP_SIZES;
4514
4923
  exports.CONTROL_FIELD_VARIANTS = CONTROL_FIELD_VARIANTS;
4515
4924
  exports.CONTROL_SIZES = CONTROL_SIZES;
4516
4925
  exports.PAGINATION_ALIGNS = PAGINATION_ALIGNS;
4517
4926
  exports.VApp = VApp;
4927
+ exports.VAvatar = VAvatar;
4518
4928
  exports.VBreadcrumbs = VBreadcrumbs;
4929
+ exports.VBusyImage = VBusyImage;
4519
4930
  exports.VButton = VButton;
4520
4931
  exports.VButtonGroup = VButtonGroup;
4521
4932
  exports.VCard = VCard;
@@ -4523,6 +4934,7 @@ exports.VCardActions = VCardActions;
4523
4934
  exports.VCardContent = VCardContent;
4524
4935
  exports.VCheckbox = VCheckbox;
4525
4936
  exports.VCheckboxGroup = VCheckboxGroup;
4937
+ exports.VChip = VChip;
4526
4938
  exports.VContentSwitcher = VContentSwitcher;
4527
4939
  exports.VDataTable = VDataTable;
4528
4940
  exports.VDrawerLayout = VDrawerLayout;
@@ -4542,6 +4954,7 @@ exports.VPaper = VPaper;
4542
4954
  exports.VRadio = VRadio;
4543
4955
  exports.VRadioGroup = VRadioGroup;
4544
4956
  exports.VSelect = VSelect;
4957
+ exports.VSkeltonLoaderBone = VSkeltonLoaderBone;
4545
4958
  exports.VSwitch = VSwitch;
4546
4959
  exports.VSwitchGroup = VSwitchGroup;
4547
4960
  exports.VTabs = VTabs;
@@ -4579,7 +4992,9 @@ exports.WysiwygLinkTool = WysiwygLinkTool;
4579
4992
  exports.WysiwygOrderedListTool = WysiwygOrderedListTool;
4580
4993
  exports.WysiwygTextColorTool = WysiwygTextColorTool;
4581
4994
  exports.configureDataTableDefaults = configureDataTableDefaults;
4995
+ exports.createAvatarProps = createAvatarProps;
4582
4996
  exports.createCardProps = createCardProps;
4997
+ exports.createChipProps = createChipProps;
4583
4998
  exports.createControlFieldProviderProps = createControlFieldProviderProps;
4584
4999
  exports.createControlProps = createControlProps;
4585
5000
  exports.createElevationProps = createElevationProps;
@@ -4602,6 +5017,7 @@ exports.renderNavigationItemInput = renderNavigationItemInput;
4602
5017
  exports.resolveNavigationItemInput = resolveNavigationItemInput;
4603
5018
  exports.resolveRawIconProp = resolveRawIconProp;
4604
5019
  exports.resolveRawWysiwygEditorTools = resolveRawWysiwygEditorTools;
5020
+ exports.splitAttrs = splitAttrs;
4605
5021
  exports.useControl = useControl;
4606
5022
  exports.useControlField = useControlField;
4607
5023
  exports.useElevation = useElevation;