@mixd-id/web-scaffold 0.1.250801008 → 0.1.250801009

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,7 +1,7 @@
1
1
  {
2
2
  "name": "@mixd-id/web-scaffold",
3
3
  "private": false,
4
- "version": "0.1.250801008",
4
+ "version": "0.1.250801009",
5
5
  "scripts": {
6
6
  "dev": "vite serve",
7
7
  "build": "vite build",
@@ -19,13 +19,13 @@
19
19
  </div>
20
20
  </slot>
21
21
 
22
- <slot name="default"></slot>
22
+ <slot name="default" :context="context"></slot>
23
23
 
24
24
  </div>
25
25
  </Transition>
26
26
  </Teleport>
27
27
  <div v-else :class="computedClass">
28
- <slot name="default"></slot>
28
+ <slot name="default" :context="context"></slot>
29
29
  </div>
30
30
  </template>
31
31
 
@@ -76,7 +76,8 @@ export default{
76
76
  data(){
77
77
  return {
78
78
  mounted: false,
79
- _state: false
79
+ _state: false,
80
+ context: {}
80
81
  }
81
82
  },
82
83
 
@@ -100,7 +101,9 @@ export default{
100
101
 
101
102
  },
102
103
 
103
- open(){
104
+ open(context = {}){
105
+ this.context = context
106
+
104
107
  if(this.query){
105
108
 
106
109
  }
@@ -129,6 +132,11 @@ export default{
129
132
 
130
133
  class: String,
131
134
 
135
+ dismissable: {
136
+ type: Boolean,
137
+ default: false
138
+ },
139
+
132
140
  float: Boolean,
133
141
 
134
142
  height: {
@@ -218,4 +226,13 @@ html[data-theme='dark'] .overlay{
218
226
  @apply bg-black/50;
219
227
  }
220
228
 
229
+ @media screen and (max-width: 640px){
230
+
231
+ .modal {
232
+ width: 100% !important;
233
+ max-height: 90vh;
234
+ @apply self-end;
235
+ }
236
+
237
+ }
221
238
  </style>
@@ -1,5 +1,6 @@
1
1
  <template>
2
- <div class="flex flex-col">
2
+ <div class="flex flex-col bg-base-400 md:bg-transparent"
3
+ v-intersect="onVisibleChange">
3
4
 
4
5
  <div v-if="readyState >= 1"
5
6
  class="flex-1 flex flex-row">
@@ -36,14 +37,14 @@
36
37
  :preset="preset"
37
38
  :presetSelector="$refs.presetSelector"
38
39
  :compPrefix="compPrefix">
39
- <div class="flex flex-col md:flex-row gap-3 md:items-end overflow-hidden p-3 md:p-0 md:panel-none border-b-[1px] border-border-50 md:border-none"
40
+ <div class="flex flex-col md:flex-row gap-3 md:items-end overflow-hidden p-3 pb-1 md:p-0"
40
41
  :class="headerClass">
41
-
42
- <div class="flex md:flex-1 flex-row items-end gap-3">
42
+ <div class="flex md:flex-1 flex-row items-end md:gap-3 py-1 md:py-0">
43
+ <slot name="left"></slot>
43
44
 
44
45
  <div class="flex flex-row gap-2 md:gap-3 items-center px-3" ref="title">
45
46
  <div class="flex flex-col whitespace-nowrap text-ellipsis overflow-hidden">
46
- <div class="cursor-pointer group leading-5" @click="$refs.contextMenu.open($refs.title)">
47
+ <div class="cursor-pointer group leading-4" @click="$refs.contextMenu.open($refs.title)">
47
48
  <small class="text-text-400 text-xs">{{ title ?? 'Untitled' }}</small>
48
49
  <div class="flex flex-row items-baseline gap-1">
49
50
  <h3 class="whitespace-nowrap relative text-ellipsis overflow-hidden group-hover:text-primary">
@@ -90,8 +91,9 @@
90
91
 
91
92
  <slot name="toolbar">
92
93
  </slot>
94
+
93
95
  <slot name="right-toolbar">
94
- <div class="flex flex-row gap-2" v-if="Boolean(toolbar)">
96
+ <div class="hidden md:flex flex-row gap-2" v-if="Boolean(toolbar)">
95
97
  <Textbox v-if="canSearch"
96
98
  class="flex-1 md:w-[240px]"
97
99
  placeholder="Search..."
@@ -106,26 +108,6 @@
106
108
  </div>
107
109
  </template>
108
110
  </Textbox>
109
-
110
- <div v-if="false && $slots.gridItem"
111
- class="hidden md:grid grid-cols-2 gap-[1px] border-[1px] border-border-50 rounded-lg">
112
- <Radio v-model="preset.view"
113
- name="view"
114
- value="table"
115
- :custom="true"
116
- class="p-2 px-3 rounded-lg rounded-r-none"
117
- :class="preset.view === 'table' ? 'bg-primary-500' : 'bg-base-500'">
118
- <svg width="14" height="14" :class="preset.view === 'table' ? 'fill-white' : 'fill-text'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M448 32H64.05C28.7 32 .0492 60.65 .0492 96v320c0 35.35 28.65 64 64 64h383.1c35.35 0 64-28.65 64-64V96C512 60.65 483.4 32 448 32zM224 416H64v-96h160V416zM224 256H64V160h160V256zM448 416h-160v-96h160V416zM448 256h-160V160h160V256z"/></svg>
119
- </Radio>
120
- <Radio v-model="preset.view"
121
- name="view"
122
- value="grid"
123
- :custom="true"
124
- class="p-2 px-3 bg-base-500 rounded-lg rounded-l-none"
125
- :class="preset.view === 'grid' ? 'bg-primary-500' : 'bg-base-500'">
126
- <svg width="14" height="14" :class="preset.view === 'grid' ? 'fill-white' : 'fill-text'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M144 288h-96c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32v-96C176 302.3 161.7 288 144 288zM368 288h-96c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32v-96C400 302.3 385.7 288 368 288zM592 288h-96c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32v-96C624 302.3 609.7 288 592 288zM144 64h-96c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32V96C176 78.33 161.7 64 144 64zM368 64h-96c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32V96C400 78.33 385.7 64 368 64zM592 64h-96c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32V96C624 78.33 609.7 64 592 64z"/></svg>
127
- </Radio>
128
- </div>
129
111
  </div>
130
112
  </slot>
131
113
  </div>
@@ -133,6 +115,27 @@
133
115
  </div>
134
116
  </slot>
135
117
 
118
+ <div class="md:hidden">
119
+ <slot name="mobile-toolbar">
120
+ <div class="p-3">
121
+ <Textbox v-if="canSearch"
122
+ placeholder="Search..."
123
+ class="bg-base-300"
124
+ clearable="1"
125
+ maxlength="100"
126
+ v-model="preset.search"
127
+ @clear="delete preset.search; load()"
128
+ @keyup.enter="load">
129
+ <template #start>
130
+ <div class="p-2 pr-0">
131
+ <svg width="14" height="14" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M504.1 471l-134-134C399.1 301.5 415.1 256.8 415.1 208c0-114.9-93.13-208-208-208S-.0002 93.13-.0002 208S93.12 416 207.1 416c48.79 0 93.55-16.91 129-45.04l134 134C475.7 509.7 481.9 512 488 512s12.28-2.344 16.97-7.031C514.3 495.6 514.3 480.4 504.1 471zM48 208c0-88.22 71.78-160 160-160s160 71.78 160 160s-71.78 160-160 160S48 296.2 48 208z"/></svg>
132
+ </div>
133
+ </template>
134
+ </Textbox>
135
+ </div>
136
+ </slot>
137
+ </div>
138
+
136
139
  <div class="flex-1 flex" ref="content">
137
140
  <div v-if="readyState === 2" class="flex-1 flex items-center justify-center">
138
141
  <svg class="animate-spin" width="36" height="36" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>
@@ -288,7 +291,7 @@ import VirtualGrid from "./VirtualGrid.vue";
288
291
  import PresetSelector from "../widgets/PresetSelector.vue";
289
292
  import {generatePivotColumns, generateTotalColumns, setupConfig, sortsFn} from "../utils/preset-selector.mjs";
290
293
  import PresetBar from "../widgets/PresetBar.vue";
291
- import {groupBy, invokeAfterIdle, queueForLater} from "../utils/helpers.mjs";
294
+ import {invokeAfterIdle, queueForLater} from "../utils/helpers.mjs";
292
295
 
293
296
  export default{
294
297
 
@@ -899,40 +902,42 @@ export default{
899
902
  if(column){
900
903
  delete column.freeze
901
904
  }
902
- }
905
+ },
903
906
 
904
- },
907
+ onVisibleChange({ inViewport, entry }){
908
+ if(inViewport){
909
+ this.$addResizeListener(this.$el, () => this.compPrefix = this.$util.calculateMediaPrefix(this.$el.clientWidth))
910
+
911
+ this.loadPreset()
912
+ .finally(() => {
913
+ this.readyState = 1
914
+ this.$nextTick(() => {
915
+ this.calcItemsPerPage()
916
+ this.load()
917
+ this.loadExt()
918
+ })
919
+ })
905
920
 
906
- components: {PresetBar, PresetSelector, VirtualGrid, VirtualTable},
921
+ if(this.subscribeKey){
922
+ this.useSocket().send('user.subscribe', { name:this.subscribeKey })
923
+ this.useSocket().on(this.subscribeKey, this.onSignal)
924
+ }
907
925
 
908
- mounted(){
909
- this.$addResizeListener(this.$el, () => this.compPrefix = this.$util.calculateMediaPrefix(this.$el.clientWidth))
926
+ window.addEventListener('keydown', this.onKeyDown)
910
927
 
911
- this.loadPreset()
912
- .finally(() => {
913
- this.readyState = 1
914
- this.$nextTick(() => {
915
- this.calcItemsPerPage()
916
- this.load()
917
- this.loadExt()
918
- })
928
+ this.queue = queueForLater({
929
+ pop: this.loadQueued,
930
+ delay: this.updateInterval
919
931
  })
920
932
 
921
- if(this.subscribeKey){
922
- this.useSocket().send('user.subscribe', { name:this.subscribeKey })
923
- this.useSocket().on(this.subscribeKey, this.onSignal)
924
- }
925
-
926
- window.addEventListener('keydown', this.onKeyDown)
927
-
928
- this.queue = queueForLater({
929
- pop: this.loadQueued,
930
- delay: this.updateInterval
931
- })
933
+ this.useSocket().on('connect', this.onConnect)
934
+ }
935
+ },
932
936
 
933
- this.useSocket().on('connect', this.onConnect)
934
937
  },
935
938
 
939
+ components: {PresetBar, PresetSelector, VirtualGrid, VirtualTable},
940
+
936
941
  unmounted() {
937
942
  this.$removeResizeListener(this.$el)
938
943
  window.removeEventListener('keydown', this.onKeyDown)
@@ -92,7 +92,7 @@ export default{
92
92
 
93
93
  .timepicker{
94
94
  @apply inline-flex flex-row items-center;
95
- @apply bg-base-300 border-[1px] border-border-200 rounded-lg;
95
+ @apply bg-base-400 border-[1px] border-border-200 rounded-lg;
96
96
  @apply divide-x divide-border-50;
97
97
  }
98
98
 
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div :class="$style.virtualGrid" @click="resize">
2
+ <div :class="$style.virtualGrid">
3
3
 
4
4
  <div ref="scroller" :class="$style.scroller" :style="scrollerStyle">
5
5
  <div :class="spacerClass" ref="spacer" :style="spacerStyle">
@@ -273,7 +273,7 @@ export default{
273
273
 
274
274
  .virtualGrid{
275
275
  @apply flex-1 overflow-y-auto;
276
- @apply border-[1px] border-border-50 bg-base-400;
276
+ @apply md:border-[1px] border-border-50 md:bg-base-400;
277
277
  }
278
278
 
279
279
  .scroller{
@@ -286,7 +286,7 @@ export default{
286
286
  .spacer{
287
287
  will-change: auto;
288
288
  position: relative;
289
- @apply grid;
289
+ @apply grid divide-y divide-border-50 border-t-[1px] border-border-50;
290
290
  }
291
291
 
292
292
  .calc{
@@ -0,0 +1,26 @@
1
+ // directives/intersect.js
2
+ export default {
3
+ mounted(el, binding) {
4
+ const callback = binding.value;
5
+
6
+ const observer = new IntersectionObserver(
7
+ (entries) => {
8
+ entries.forEach(entry => {
9
+ callback({
10
+ inViewport: entry.isIntersecting,
11
+ entry
12
+ });
13
+ });
14
+ },
15
+ {
16
+ threshold: 0.1, // adjust sensitivity
17
+ }
18
+ );
19
+
20
+ observer.observe(el);
21
+ el._observer = observer;
22
+ },
23
+ unmounted(el) {
24
+ if (el._observer) el._observer.disconnect();
25
+ }
26
+ };
package/src/index.js CHANGED
@@ -2,6 +2,8 @@ import {defineAsyncComponent, ref} from "vue"
2
2
  import {arrayPush, arrayRemove, arrayUnshift, downloadUrl, invokeAfterIdle, observeInit} from './utils/helpers.mjs'
3
3
  import dayjs from "dayjs";
4
4
  import {useDevice} from './hooks/device.js'
5
+ import IntersectDirective from './directives/intersect';
6
+
5
7
 
6
8
  let _UNIQID = 0
7
9
  const uniqid = (additionalKey = '') => {
@@ -425,6 +427,8 @@ export default{
425
427
  app.config.globalProperties.$mounted.value = true
426
428
  }
427
429
 
430
+ app.directive('intersect', IntersectDirective)
431
+
428
432
  app.component('Ahref', defineAsyncComponent(() => import("./components/Ahref.vue")))
429
433
  app.component('Paragraph', defineAsyncComponent(() => import("./components/Paragraph.vue")))
430
434
  app.component('Alert', defineAsyncComponent(() => import("./components/Alert.vue")))