bt-core-app 0.0.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.
Files changed (53) hide show
  1. package/.vscode/extensions.json +3 -0
  2. package/README.md +45 -0
  3. package/index.html +13 -0
  4. package/package.json +39 -0
  5. package/public/vite.svg +1 -0
  6. package/src/assets/vue.svg +1 -0
  7. package/src/components/BT-Btn.vue +40 -0
  8. package/src/components/BT-Col.vue +36 -0
  9. package/src/components/BT-Span.vue +21 -0
  10. package/src/components/Dialog-Confirm.vue +47 -0
  11. package/src/components/Dialog-Select-Date.vue +89 -0
  12. package/src/components/Dialog-Select.vue +140 -0
  13. package/src/components/Dialog-Text.vue +59 -0
  14. package/src/composables/actions-tracker.ts +99 -0
  15. package/src/composables/actions.ts +354 -0
  16. package/src/composables/api.ts +471 -0
  17. package/src/composables/auth.ts +382 -0
  18. package/src/composables/cosmetics.ts +178 -0
  19. package/src/composables/csv.ts +198 -0
  20. package/src/composables/dates.ts +79 -0
  21. package/src/composables/demo.ts +25 -0
  22. package/src/composables/dialogs.ts +115 -0
  23. package/src/composables/document-meta.ts +40 -0
  24. package/src/composables/draggable.ts +189 -0
  25. package/src/composables/filters.ts +256 -0
  26. package/src/composables/forage.ts +49 -0
  27. package/src/composables/helpers.ts +694 -0
  28. package/src/composables/id.ts +20 -0
  29. package/src/composables/list.ts +601 -0
  30. package/src/composables/navigation.ts +214 -0
  31. package/src/composables/presets.ts +20 -0
  32. package/src/composables/pwa.ts +89 -0
  33. package/src/composables/resizable.ts +382 -0
  34. package/src/composables/rules.ts +40 -0
  35. package/src/composables/stores.ts +797 -0
  36. package/src/composables/track.ts +55 -0
  37. package/src/composables/urls.ts +11 -0
  38. package/src/core.ts +92 -0
  39. package/src/index.ts +16 -0
  40. package/src/types.ts +13 -0
  41. package/src/useApi.ts +68 -0
  42. package/src/vite-env.d.ts +1 -0
  43. package/test/api.test.ts +84 -0
  44. package/test/forage.test.ts +31 -0
  45. package/test/helpers.test.ts +231 -0
  46. package/test/navigation.test.ts +99 -0
  47. package/test/stores-last-update.test.ts +138 -0
  48. package/test/stores-session.test.ts +118 -0
  49. package/test/track.test.ts +29 -0
  50. package/test/utils.ts +15 -0
  51. package/tsconfig.json +33 -0
  52. package/tsconfig.node.json +11 -0
  53. package/vite.config.ts +19 -0
@@ -0,0 +1,214 @@
1
+ //nav item needs to have a 'ignore Suspension' prop
2
+ import { useUrl } from '@/composables/urls'
3
+ import { appendUrl, deepSelect } from '@/composables/helpers'
4
+ import { ref, type Ref } from 'vue'
5
+ import { type AuthItem } from './auth'
6
+
7
+ export interface ExternalParty {
8
+ party?: string
9
+ property?: string
10
+ }
11
+
12
+ export interface ExternalNavigation {
13
+ canPull?: boolean
14
+ canPush?: boolean
15
+ convertFunc?: Function
16
+ name?: string
17
+ localNavigation?: string
18
+ localDisplayPath?: string
19
+ localComparePath?: string
20
+ syncComparePath?: string
21
+ syncDisplayPath?: string
22
+ syncIDPath?: string
23
+ }
24
+
25
+ export interface NavigationItem extends AuthItem {
26
+ /**aliases are other names that could use this navigation item's set of permissions, etc.*/
27
+ aliases?: string[]
28
+ /**potentially the nav that leads to the archive */
29
+ archiveName?: string
30
+ /**the name of the background img to show when the route opens this nav */
31
+ background?: string
32
+ /**how long until locally cached data is refreshed */
33
+ cacheExpiryHours?: number
34
+ /**any children of this nav item */
35
+ children?: NavigationItem[]
36
+ /**the name that will be displayed in the navigation menu */
37
+ displayName?: string
38
+ /**where credentials can be found for external parties*/
39
+ externalPartyCredentialNavigation?: string
40
+ /**possible external parties to connect to and sync with */
41
+ externalParties?: ExternalParty[]
42
+ /**possible external party navigation items and how to connect/sync */
43
+ externalNavigations?: ExternalNavigation[]
44
+ /**will hide app bar if set to true when the route opens this nav */
45
+ hideAppBar?: boolean
46
+ /**will hide the nav sidebar if set to true when the route opens this nav */
47
+ hideNavigation?: boolean
48
+ /**will open a dialog box to confirm navigating away from this route */
49
+ hesitate?: boolean
50
+ /**the mdi icon that goes with this nav item. Will show in places like the nav menu */
51
+ icon?: string
52
+ /**default to false. True will mean that even is account is suspended, this will still allow navigation */
53
+ ignoreSuspension?: boolean
54
+ /**default to true. When false will hide from nav menu */
55
+ isInNavMenu?: boolean
56
+ /**the microservice the leads to the default url to obtain data from. Defaults to 'default'. */
57
+ microservice?: string
58
+ /**the name of this nav item. */
59
+ name?: string
60
+ /**the url path on top of the base microservice url */
61
+ path?: string
62
+ /**permissions that are required for this navItem. All these permissions must be met. */
63
+ permissions?: string[]
64
+ /**default to true. When false will allow universal access regardless of permission */
65
+ requiresAuth?: boolean
66
+ /**the name of the route to access individual items */
67
+ singleName?: string
68
+ /**this nav item is restricted to these subscriptions. So the user needs to have at least one of these subscription codes. */
69
+ subscriptions?: string[]
70
+ /**this nav item is preferred in this subscription codes. */
71
+ subFilters?: string[]
72
+ }
73
+
74
+ const appBar = ref(true)
75
+ const appNavigation = ref(false)
76
+ const backgroundName: Ref<string | undefined> = ref()
77
+ const hesitate = ref(false)
78
+ let removeHesitateListener: any = null
79
+
80
+ export interface BTNavigation {
81
+ showAppBar: Ref<boolean>
82
+ showAppNavigation: Ref<boolean>
83
+ backgroundName: Ref<string | undefined>
84
+ hesitate: Ref<boolean>
85
+ navigationItems: NavigationItem[],
86
+ findArchiveName: (navName?: string) => string | undefined
87
+ findCacheHours: (navName?: string) => number
88
+ findDisplay: (navName?: string) => string | undefined
89
+ findIcon: (navName?: string) => string | undefined
90
+ findItem: (navName?: string | NavigationItem) => NavigationItem | null
91
+ findStoreName: (navName?: string) => string
92
+ findPath: (navName?: string) => string | undefined
93
+ findSingleDisplay: (navName?: string) => string | undefined
94
+ updateNavigationProperties: (navName?: string | NavigationItem) => void
95
+ }
96
+
97
+ interface UseNavigationOptions {
98
+ defaultCacheExpiryHours?: number
99
+ navItems?: NavigationItem[]
100
+ }
101
+
102
+ export function createNavigation(options: UseNavigationOptions): BTNavigation {
103
+ const cacheExpiryHours = options.defaultCacheExpiryHours ?? 7
104
+ const navigationList = options.navItems ?? []
105
+
106
+ function findArchiveName(navName?: string): string | undefined {
107
+ return findItem(navName)?.archiveName
108
+ }
109
+
110
+ function findCacheHours(navName?: string): number {
111
+ return findItem(navName)?.cacheExpiryHours ?? cacheExpiryHours
112
+ }
113
+
114
+ function findDisplay(navName?: string): string | undefined {
115
+ return findItem(navName)?.displayName
116
+ }
117
+
118
+ function findIcon(navName?: string): string | undefined {
119
+ return findItem(navName)?.icon
120
+ }
121
+
122
+ function findItem(navName?: string | NavigationItem) {
123
+ if (navName == null) return null
124
+ if (typeof navName != 'string') return navName
125
+
126
+ const items = deepSelect(navigationList, (x: NavigationItem) => x.children) as NavigationItem[]
127
+
128
+ return items.find(navItem => navItem.name == navName ||
129
+ navItem.singleName == navName ||
130
+ navItem.aliases?.some(y => y == navName)) ?? null
131
+ }
132
+
133
+ /**defaults to microservice of default */
134
+ function findPath(navName?: string) {
135
+ const navItem = findItem(navName)
136
+ if (navItem == null) return undefined
137
+
138
+ let vPath = useUrl(navItem.microservice ?? 'default') ?? ''
139
+
140
+ if (navItem.path != null)
141
+ vPath = appendUrl(vPath, navItem.path)
142
+
143
+ if (vPath?.endsWith('/'))
144
+ vPath = vPath.slice(0, vPath.length - 1)
145
+
146
+ return vPath
147
+ }
148
+
149
+ /**finds display name and attempts to remove plural suffixes */
150
+ function findSingleDisplay(navName?: string): string | undefined {
151
+ const item = findItem(navName)
152
+
153
+ if (item?.singleName != null)
154
+ return item.singleName
155
+
156
+ const displayName = item?.displayName
157
+
158
+ if (displayName == null) return undefined
159
+
160
+ if (displayName.endsWith('ies'))
161
+ return displayName.slice(0, displayName.length - 3)
162
+
163
+ if (displayName.endsWith('es'))
164
+ return displayName.slice(0, displayName.length - 2)
165
+
166
+ if (displayName.endsWith('s'))
167
+ return displayName.slice(0, displayName.length - 1)
168
+
169
+ return displayName
170
+ }
171
+
172
+ function findStoreName(navName?: string) {
173
+ const navItem = findItem(navName)
174
+ return navItem?.name ?? navItem?.singleName ?? 'store'
175
+ }
176
+
177
+ /**updates background, navigation sidebar, and app bar settings */
178
+ function updateNavigationProperties(navName?: string | NavigationItem) {
179
+ if (navName == null) return
180
+
181
+ const item = typeof navName == 'string' ? findItem(navName) : navName
182
+
183
+ backgroundName.value = item?.background
184
+ appNavigation.value = item?.hideNavigation !== true
185
+ appBar.value = item?.hideAppBar !== true
186
+
187
+ if (removeHesitateListener != null)
188
+ removeHesitateListener()
189
+
190
+ hesitate.value = item?.hesitate === true
191
+
192
+ if (hesitate.value)
193
+ removeHesitateListener = window.addEventListener('beforeunload', e => {
194
+ e.preventDefault()
195
+ })
196
+ }
197
+
198
+ return {
199
+ showAppBar: appBar,
200
+ showAppNavigation: appNavigation,
201
+ backgroundName,
202
+ hesitate,
203
+ navigationItems: navigationList,
204
+ findArchiveName,
205
+ findCacheHours,
206
+ findDisplay,
207
+ findIcon,
208
+ findItem,
209
+ findStoreName,
210
+ findPath,
211
+ findSingleDisplay,
212
+ updateNavigationProperties
213
+ }
214
+ }
@@ -0,0 +1,20 @@
1
+ export interface BTPresets {
2
+ usePresets(preset?: string): any
3
+ }
4
+
5
+ export interface CreatePresetsOptions {
6
+ presets: any
7
+ }
8
+
9
+ export function createPresets(options: CreatePresetsOptions): BTPresets {
10
+
11
+ function usePresets(preset?: string): any {
12
+ if (!preset) return {}
13
+ let mPreset = preset as keyof typeof options.presets
14
+ return options.presets[mPreset] ?? {}
15
+ }
16
+
17
+ return {
18
+ usePresets
19
+ }
20
+ }
@@ -0,0 +1,89 @@
1
+ import { tryOnMounted } from '@vueuse/core'
2
+ import { ref, type Ref } from 'vue'
3
+
4
+ export interface SWEvent extends Event {
5
+ detail: any
6
+ }
7
+
8
+ let updateListener: void | undefined
9
+ let controllerChangeListener: void | undefined
10
+ let promptListener: void | undefined
11
+ let isUpdating = false
12
+
13
+ const canInstallApp = ref(false)
14
+ const canUpdateApp = ref(false)
15
+ const prompt: Ref<any> = ref()
16
+ const sWorker: Ref<any> = ref()
17
+
18
+ export interface BTPWA {
19
+ canInstallApp: Ref<boolean>
20
+ canUpdateApp: Ref<boolean>
21
+ installApp: () => void
22
+ isInstalled: () => boolean
23
+ updateApp: () => void
24
+ }
25
+
26
+ export function createPWA(): BTPWA {
27
+
28
+ function notifyUpdateAvailable(e: any) {
29
+ sWorker.value = e.detail
30
+ canUpdateApp.value = true
31
+ }
32
+
33
+ function controllerChanged() {
34
+ if (isUpdating) return
35
+ isUpdating = true
36
+ window.location.reload()
37
+ }
38
+
39
+ function installApp() {
40
+ prompt.value?.prompt()
41
+ canInstallApp.value = false
42
+ }
43
+
44
+ function isInstalled() {
45
+ // For iOS
46
+ // if (window.navigator.standalone) return true
47
+
48
+ // For Android
49
+ if (window.matchMedia('(display-mode: standalone)').matches) return true
50
+
51
+ // If neither is true, it's not installed
52
+ return false
53
+ }
54
+
55
+ function storePrompt(e: Event) {
56
+ e.preventDefault()
57
+ canInstallApp.value = true
58
+ prompt.value = e
59
+ }
60
+
61
+ function updateApp() {
62
+ canUpdateApp.value = false
63
+
64
+ if (!sWorker.value || !sWorker.value.waiting)
65
+ return
66
+
67
+ sWorker.value.waiting.postMessage({ type: 'SKIP_WAITING' })
68
+ }
69
+
70
+ tryOnMounted(() => {
71
+ if (updateListener == null) {
72
+ updateListener = document.addEventListener('swUpdated', notifyUpdateAvailable, { once: true })
73
+ }
74
+
75
+ if (controllerChangeListener == null)
76
+ controllerChangeListener = navigator.serviceWorker.addEventListener('controllerchange', controllerChanged)
77
+
78
+ if (promptListener == null)
79
+ promptListener = window.addEventListener('beforeinstallprompt', storePrompt)
80
+ })
81
+
82
+ return {
83
+ canInstallApp,
84
+ canUpdateApp,
85
+ installApp,
86
+ isInstalled,
87
+ updateApp
88
+ }
89
+ }
@@ -0,0 +1,382 @@
1
+ import { toValue, useEventListener, useParentElement } from "@vueuse/core"
2
+ import { type ComponentPublicInstance, type Ref, ref } from 'vue'
3
+ import type { Position, MaybeRefOrGetter } from "@vueuse/core"
4
+ import { copyDeep } from "@/composables/helpers"
5
+ import { type BladeVariant } from "@/types"
6
+
7
+ export type ResizeHandle = 't' | 'r' | 'b' | 'l' | 'tr' | 'br' | 'bl' | 'tl'
8
+
9
+ export interface PointerOrTouchEvent extends PointerEvent, TouchEvent { }
10
+
11
+ const allHandles: ResizeHandle[] = ['t', 'r', 'b', 'l', 'tr', 'br', 'bl', 'tl']
12
+
13
+ export interface UseResizeOptions {
14
+ preventDefault?: MaybeRefOrGetter<boolean>
15
+ stopPropagation?: MaybeRefOrGetter<boolean>
16
+ // pointerTypes?: PointerType[]
17
+ handles?: ResizeHandle[]
18
+
19
+ /**
20
+ * Callback when the dragging starts. Return `false` to prevent dragging.
21
+ */
22
+ onStart?: (position: Position, event: PointerEvent) => void | false
23
+
24
+ /**
25
+ * Callback during dragging.
26
+ */
27
+ onMove?: (position: Position, event: PointerEvent) => void
28
+
29
+ /**
30
+ * Callback when dragging end.
31
+ */
32
+ onEnd?: (position: Position, event: PointerEvent) => void
33
+
34
+ minWidth?: number
35
+ maxWidth?: number
36
+ minHeight?: number
37
+ maxHeight?: number
38
+ handleWidth?: number
39
+ handleZIndex?: number
40
+ }
41
+
42
+ interface ElementPosition {
43
+ left?: number,
44
+ top?: number,
45
+ height?: number,
46
+ width?: number,
47
+ position?: string
48
+ }
49
+
50
+ export function useResizable(
51
+ target: MaybeRefOrGetter<ComponentPublicInstance | null>,
52
+ options: UseResizeOptions = {}) {
53
+ let currentVariant: string | undefined = undefined
54
+ let handleWidth = options.handleWidth ?? 12
55
+ let handleZIndex = options.handleZIndex ?? 100
56
+ let minWidth = options.minWidth ?? 0
57
+ let maxWidth = options.maxWidth ?? Number.MAX_SAFE_INTEGER
58
+ let minHeight = options.minHeight ?? 0
59
+ let maxHeight = options.maxHeight ?? Number.MAX_SAFE_INTEGER
60
+ let preventDefault = options.preventDefault ?? false
61
+ let stopPropagation = options.stopPropagation ?? false
62
+
63
+ let activeHandle: any
64
+ let handleEls: HTMLDivElement[] = []
65
+ const isAutoResizing = ref(false)
66
+ let listeners: Function[] = []
67
+ let moveListeners: Function[] = []
68
+ const resizingIsOn: Ref<boolean> = ref(false)
69
+ const startingPointerPosition: Ref<Position> = ref<Position>({ x: 0, y: 0 })
70
+ let startingElementPosition: ElementPosition = { left: 0, top: 0, height: 0, width: 0, position: 'absolute' }
71
+ let currentElementPosition: ElementPosition = { }
72
+ // let variantMemory: any = {}
73
+
74
+ function handleEvent(e: PointerOrTouchEvent) {
75
+ if (toValue(preventDefault))
76
+ e.preventDefault()
77
+ if (toValue(stopPropagation))
78
+ e.stopPropagation()
79
+ }
80
+
81
+ function addHandles(el: ComponentPublicInstance, handles: ResizeHandle[]) {
82
+ handleEls = handles.map(createHandleEl)
83
+ handleEls.forEach(handleEl => el.$el.appendChild(handleEl))
84
+ }
85
+
86
+ function removeHandles(el: ComponentPublicInstance) {
87
+ handleEls.forEach(handleEl => el.$el.removeChild(handleEl))
88
+ }
89
+
90
+ function createHandleEl(handle: string): HTMLDivElement { //ComponentPublicInstance {
91
+ const handleWidthPx = handleWidth + 'px'
92
+ const handleOffsetPx = -handleWidth / 2 + 'px'
93
+ const handleCornerZIndex = handleZIndex + 1
94
+
95
+ const handleEl = document.createElement('div')
96
+ handleEl.dataset.handle = handle
97
+ handleEl.style.position = 'absolute'
98
+ handleEl.style.touchAction = 'none'
99
+ handleEl.style.userSelect = 'none'
100
+ handleEl.style.zIndex = (handle.length === 1 ? handleZIndex : handleCornerZIndex).toString()
101
+ handleEl.style.cursor = getCursor(handle)
102
+
103
+ if (handle.includes('t')) {
104
+ handleEl.style.top = handleOffsetPx
105
+ handleEl.style.height = handleWidthPx
106
+ if (handle === 't') {
107
+ handleEl.style.left = '0'
108
+ handleEl.style.width = '100%'
109
+ }
110
+ }
111
+ if (handle.includes('b')) {
112
+ handleEl.style.bottom = handleOffsetPx
113
+ handleEl.style.height = handleWidthPx
114
+ if (handle === 'b') {
115
+ handleEl.style.left = '0'
116
+ handleEl.style.width = '100%'
117
+ }
118
+ }
119
+ if (handle.includes('r')) {
120
+ handleEl.style.right = handleOffsetPx
121
+ handleEl.style.width = handleWidthPx
122
+ if (handle === 'r') {
123
+ handleEl.style.top = '0'
124
+ handleEl.style.height = '100%'
125
+ }
126
+ }
127
+ if (handle.includes('l')) {
128
+ handleEl.style.left = handleOffsetPx
129
+ handleEl.style.width = handleWidthPx
130
+ if (handle === 'l') {
131
+ handleEl.style.top = '0'
132
+ handleEl.style.height = '100%'
133
+ }
134
+ }
135
+ return handleEl
136
+ }
137
+
138
+ function start(e: PointerOrTouchEvent) {
139
+ if (!handleEls.some(x => x == e.target)) return
140
+ const t = toValue(target)
141
+ if (!t) return
142
+ const el = t.$el
143
+ const isTouch = e.type === 'touchstart' && e.touches.length > 0
144
+ const evtData = isTouch ? e.touches[0] : e
145
+
146
+ startingPointerPosition.value.x = evtData.clientX
147
+ startingPointerPosition.value.y = evtData.clientY
148
+
149
+ startingElementPosition = {
150
+ left: el.offsetLeft,
151
+ top: el.offsetTop,
152
+ height: parseInt(window.getComputedStyle(el).getPropertyValue('height')),
153
+ width: parseInt(window.getComputedStyle(el).getPropertyValue('width'))
154
+ }
155
+
156
+ currentElementPosition = copyDeep(startingElementPosition)
157
+
158
+ if (options.onStart?.(startingPointerPosition.value, e) === false) return
159
+
160
+ let handle = e.target as HTMLElement
161
+
162
+ document.documentElement.style.cursor = getCursor(handle.dataset.handle as string)
163
+ activeHandle = handle.dataset.handle as string
164
+
165
+ moveListeners.push(useEventListener('mousemove', move))
166
+ moveListeners.push(useEventListener('mouseup', end))
167
+ moveListeners.push(useEventListener('touchmove', move))
168
+ moveListeners.push(useEventListener('touchend', end))
169
+
170
+ handleEvent(e)
171
+ }
172
+
173
+ function move(e: any) {
174
+ const t = toValue(target)
175
+ if (!t) return
176
+ const el = t.$el
177
+
178
+ const isTouch = e.type === 'touchmove' && e.touches.length > 0
179
+ const evtData = isTouch ? e.touches[0] : e
180
+ let dx = evtData.clientX - startingPointerPosition.value.x
181
+ let dy = evtData.clientY - startingPointerPosition.value.y
182
+ const start = toValue(startingElementPosition)
183
+
184
+ if (activeHandle.includes('t')) {
185
+ const newHeight = Math.min(maxHeight, Math.max(minHeight, (start.height ?? 0) - dy))
186
+ currentElementPosition.height = newHeight
187
+ currentElementPosition.top = (start.top ?? 0) + dy
188
+ }
189
+ if (activeHandle.includes('b')) {
190
+ const newHeight = Math.min(maxHeight, Math.max(minHeight, (start.height ?? 0) + dy))
191
+ currentElementPosition.height = newHeight
192
+ }
193
+ if (activeHandle.includes('l')) {
194
+ const newWidth = Math.min(maxWidth, Math.max(minWidth, (start.width ?? 0) - dx))
195
+ currentElementPosition.width = newWidth
196
+ currentElementPosition.left = (start.left ?? 0) + dx
197
+ }
198
+ if (activeHandle.includes('r')) {
199
+ const newWidth = Math.min(maxWidth, Math.max(minWidth, (start.width ?? 0) + dx))
200
+ currentElementPosition.width = newWidth
201
+ }
202
+
203
+ el.dispatchEvent(new CustomEvent('resize'))
204
+ handleEvent(e)
205
+
206
+ applyToElementStyle(currentElementPosition)
207
+ }
208
+
209
+ function end() {
210
+ document.documentElement.style.cursor = ''
211
+ activeHandle = null
212
+ moveListeners.forEach(l => { l() })
213
+ moveListeners.length = 0
214
+ }
215
+
216
+ function getCursor(handle: string) {
217
+ const cursorDirection: any = {
218
+ t: 'n',
219
+ r: 'e',
220
+ b: 's',
221
+ l: 'w'
222
+ }
223
+ return (handle.split('').map(l => cursorDirection[l]).join('') + '-resize')
224
+ }
225
+
226
+ function restoreSize(variant?: BladeVariant | undefined) {
227
+ const t = toValue(target)
228
+ if (!t) return
229
+ const el = t.$el as HTMLElement
230
+ console.log(currentVariant)
231
+
232
+ if (currentVariant !== 'page' && variant == 'page') {
233
+ //moving back to default page settings
234
+ const parent = useParentElement(el)
235
+ const p = (toValue(parent) ?? null) as any
236
+ let aimWidth = 0
237
+ if (p != null) {
238
+ const c = window.getComputedStyle(p)
239
+ aimWidth = parseInt(c.getPropertyValue('width')) - p.offsetLeft
240
+ }
241
+
242
+ el.style.transition = 'width 0.5s, height 0.5s, top 0.5s, left 0.5s'
243
+ el.offsetHeight
244
+ isAutoResizing.value = true
245
+
246
+ applyToElementStyle({
247
+ height: undefined,
248
+ width: aimWidth,
249
+ top: 0,
250
+ left: 0,
251
+ position: undefined
252
+ })
253
+
254
+ useEventListener(el, 'transitionend', () => {
255
+ el.style.width = 'auto'
256
+ el.style.top = ''
257
+ el.style.left = ''
258
+ el.style.position = ''
259
+ el.style.transition = ''
260
+ isAutoResizing.value = false
261
+ }, { once: true })
262
+ }
263
+ else if ((currentVariant == 'page' || t.$el.style.position !== 'absolute') && variant !== 'page') {
264
+ //move to freestyle or blade
265
+ el.style.transition = 'width 0.5s, height 0.5s, top 0.5s, left 0.5s'
266
+ isAutoResizing.value = true
267
+
268
+ startingElementPosition = {
269
+ height: parseInt(window.getComputedStyle(el).getPropertyValue('height')),
270
+ width: parseInt(window.getComputedStyle(el).getPropertyValue('width')),
271
+ top: el.offsetTop,
272
+ left: el.offsetLeft,
273
+ position: 'absolute'
274
+ }
275
+
276
+ applyToElementStyle(startingElementPosition)
277
+ el.offsetHeight
278
+ const s = startingElementPosition
279
+
280
+ if (variant == 'freestyle') {
281
+ //half the size to indicate non-page variant
282
+ currentElementPosition = {
283
+ height: s.height,
284
+ width: (s.width ?? 100) / 2,
285
+ top: (s.top ?? 0) + 2,
286
+ left: (s.left ?? 0) + 2,
287
+ position: 'absolute'
288
+ }
289
+ }
290
+ else if (variant == 'blade') {
291
+ currentElementPosition = {
292
+ height: s.height,
293
+ width: (s.width ?? 100) / 2,
294
+ top: (s.top ?? 0) + 2,
295
+ left: (s.left ?? 0) + 2,
296
+ position: 'absolute'
297
+ }
298
+
299
+ //flex column?
300
+ }
301
+
302
+ applyToElementStyle(currentElementPosition)
303
+
304
+ useEventListener(el, 'transitionend', () => {
305
+ el.style.transition = ''
306
+ isAutoResizing.value = false
307
+ }, { once: true })
308
+ }
309
+ }
310
+
311
+ function applyToElementStyle(s: ElementPosition) {
312
+ const t = toValue(target)
313
+ if (!t) return
314
+ const el = t.$el
315
+
316
+ if (s.top) {
317
+ el.style.top = `${s.top}px`
318
+ }
319
+ else {
320
+ el.style.top = undefined
321
+ }
322
+
323
+ if (s.left) {
324
+ el.style.left = `${s.left}px`
325
+ }
326
+ else {
327
+ el.style.left = undefined
328
+ }
329
+
330
+ if (s.height) {
331
+ el.style.height = `${s.height}px`
332
+ }
333
+ else {
334
+ el.style.height = undefined
335
+ }
336
+
337
+ if (s.width) {
338
+ el.style.width = `${s.width}px`
339
+ }
340
+ else {
341
+ el.style.width = undefined
342
+ }
343
+
344
+ if (s.position) {
345
+ el.style.position = `${s.position}`
346
+ }
347
+ else {
348
+ el.style.position = undefined
349
+ }
350
+
351
+ console.log(el.style.position)
352
+ }
353
+
354
+ function turnResizingOn(handles?: ResizeHandle[], variant?: BladeVariant) {
355
+ if (resizingIsOn.value) return
356
+ const t = toValue(target)
357
+ if (!t) return
358
+ addHandles(t, handles ?? allHandles)
359
+ restoreSize(variant)
360
+ listeners.push(useEventListener(t.$el, 'mousedown', start))
361
+ listeners.push(useEventListener(t.$el, 'touchstart', start))
362
+ resizingIsOn.value = true
363
+ currentVariant = variant
364
+ }
365
+
366
+ function turnResizingOff(variant?: BladeVariant | undefined) {
367
+ if (!resizingIsOn.value) return
368
+ const t = toValue(target)
369
+ if (!t) return
370
+ removeHandles(t)
371
+ restoreSize(variant)
372
+ listeners.forEach(l => { l() })
373
+ listeners.length = 0
374
+ resizingIsOn.value = false
375
+ }
376
+
377
+ return {
378
+ resizingIsOn,
379
+ turnResizingOn,
380
+ turnResizingOff
381
+ }
382
+ }