@fastkit/vui 0.7.46 → 0.7.47

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');
@@ -409,6 +409,248 @@ function useElevation(props, opts = {}) {
409
409
  };
410
410
  }
411
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
+
412
654
  function extractRawGridValueClasses(value, prefix, getter) {
413
655
  if (typeof value !== 'object')
414
656
  return `${prefix}${getter ? getter(value) : value}`;
@@ -634,6 +876,162 @@ const VPaper = vue.defineComponent({
634
876
 
635
877
  });
636
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
+
637
1035
  function createCardProps() {
638
1036
  return { ...createPaperProps(),
639
1037
  ...vueUtils.navigationableInheritProps,
@@ -4520,11 +4918,15 @@ exports.VMenu = vueKit.VMenu;
4520
4918
  exports.VSnackbar = vueKit.VSnackbar;
4521
4919
  exports.VTooltip = vueKit.VTooltip;
4522
4920
  exports.ICON_NAMES = iconFont.ICON_NAMES;
4921
+ exports.AVATAR_SIZES = AVATAR_SIZES;
4922
+ exports.CHIP_SIZES = CHIP_SIZES;
4523
4923
  exports.CONTROL_FIELD_VARIANTS = CONTROL_FIELD_VARIANTS;
4524
4924
  exports.CONTROL_SIZES = CONTROL_SIZES;
4525
4925
  exports.PAGINATION_ALIGNS = PAGINATION_ALIGNS;
4526
4926
  exports.VApp = VApp;
4927
+ exports.VAvatar = VAvatar;
4527
4928
  exports.VBreadcrumbs = VBreadcrumbs;
4929
+ exports.VBusyImage = VBusyImage;
4528
4930
  exports.VButton = VButton;
4529
4931
  exports.VButtonGroup = VButtonGroup;
4530
4932
  exports.VCard = VCard;
@@ -4532,6 +4934,7 @@ exports.VCardActions = VCardActions;
4532
4934
  exports.VCardContent = VCardContent;
4533
4935
  exports.VCheckbox = VCheckbox;
4534
4936
  exports.VCheckboxGroup = VCheckboxGroup;
4937
+ exports.VChip = VChip;
4535
4938
  exports.VContentSwitcher = VContentSwitcher;
4536
4939
  exports.VDataTable = VDataTable;
4537
4940
  exports.VDrawerLayout = VDrawerLayout;
@@ -4551,6 +4954,7 @@ exports.VPaper = VPaper;
4551
4954
  exports.VRadio = VRadio;
4552
4955
  exports.VRadioGroup = VRadioGroup;
4553
4956
  exports.VSelect = VSelect;
4957
+ exports.VSkeltonLoaderBone = VSkeltonLoaderBone;
4554
4958
  exports.VSwitch = VSwitch;
4555
4959
  exports.VSwitchGroup = VSwitchGroup;
4556
4960
  exports.VTabs = VTabs;
@@ -4588,7 +4992,9 @@ exports.WysiwygLinkTool = WysiwygLinkTool;
4588
4992
  exports.WysiwygOrderedListTool = WysiwygOrderedListTool;
4589
4993
  exports.WysiwygTextColorTool = WysiwygTextColorTool;
4590
4994
  exports.configureDataTableDefaults = configureDataTableDefaults;
4995
+ exports.createAvatarProps = createAvatarProps;
4591
4996
  exports.createCardProps = createCardProps;
4997
+ exports.createChipProps = createChipProps;
4592
4998
  exports.createControlFieldProviderProps = createControlFieldProviderProps;
4593
4999
  exports.createControlProps = createControlProps;
4594
5000
  exports.createElevationProps = createElevationProps;
@@ -4611,6 +5017,7 @@ exports.renderNavigationItemInput = renderNavigationItemInput;
4611
5017
  exports.resolveNavigationItemInput = resolveNavigationItemInput;
4612
5018
  exports.resolveRawIconProp = resolveRawIconProp;
4613
5019
  exports.resolveRawWysiwygEditorTools = resolveRawWysiwygEditorTools;
5020
+ exports.splitAttrs = splitAttrs;
4614
5021
  exports.useControl = useControl;
4615
5022
  exports.useControlField = useControlField;
4616
5023
  exports.useElevation = useElevation;