Skip to content

Commit d475eb5

Browse files
authored
chore(release): bump version to 1.0.0-alpha.25
closes #11
2 parents d819cd4 + e89cc63 commit d475eb5

30 files changed

+344
-260
lines changed

packages/lib/src/App/app-comp.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@
176176
ab.
177177
</Scroller>
178178

179+
<Floater offset="#xxs">
180+
<IconButton icon="material-symbols:inbox-outline-rounded" />
181+
</Floater>
179182
<Floater text="3" offset="#xxs">
180183
<IconButton icon="material-symbols:inbox-outline-rounded" />
181184
</Floater>

packages/lib/src/App/app.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
}"
4444
>
4545
<template #navbar>
46-
<NavBar v-model="tab" labels="active">
46+
<NavBar v-model="tab">
4747
<NavContent mt="#xl">
4848
<SquareImage alt="App Logo" src="/favicon.svg" :size="60" />
4949
</NavContent>

packages/lib/src/App/component-state.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
import { useSnackbar } from '@/components/Snackbar/snackbar-manager'
66
import { useToast } from '@/components/Toast/toast-manager'
77
import { useLocalStorage } from '@/ref/use-local-storage'
8+
import { h } from 'vue'
89
910
import Box from '@/components/Box/box.vue'
1011
import Button from '@/components/Button/button.vue'
1112
import Select from '@/components/Select/select.vue'
1213
import Mock from './mock-content.vue'
14+
import IconButton from '@/components/Button/icon-button.vue'
1315
1416
const snackbar = useSnackbar()
1517
const modal = useModal()
@@ -51,6 +53,10 @@
5153
content: Mock,
5254
fullScreen: true,
5355
closeable: true,
56+
subAction: h(IconButton, {
57+
icon: 'material-symbols:info-outline',
58+
onClick: () => openModal()
59+
}),
5460
actions: MODAL.PRESET_ACTION_CLOSE('OK')
5561
})
5662
}

packages/lib/src/assets/layout.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,18 @@
7474
}
7575
}
7676

77+
@media (prefers-reduced-motion) {
78+
:root,
79+
.md-theme-provider {
80+
*,
81+
*::before,
82+
*::after {
83+
animation-duration: 0s !important;
84+
transition-duration: 0s !important;
85+
}
86+
}
87+
}
88+
7789
@keyframes focus {
7890
0% {
7991
outline-width: 0;

packages/lib/src/components/AppBar/top-bar.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
position: absolute;
7474
background-color: inherit;
7575
display: flex;
76+
align-items: center;
7677
right: 0;
7778
}
7879
}

packages/lib/src/components/Image/block-image.vue

Lines changed: 20 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,14 @@
33
44
import type { BoxProps } from '@/components/Box/util'
55
import type { Component } from 'vue'
6-
import type { Status } from './util'
76
8-
import { customRef } from '@/ref/custom-ref'
9-
import { useRect } from '@/ref/use-rect'
10-
import { clean } from '@/utils/object/data'
11-
import { assert } from '@/utils/object/is'
12-
import { onUnmounted, ref, shallowReactive, watch } from 'vue'
13-
import { getData } from './util'
7+
import { useFetch } from '@/ref/use-fetch'
8+
import { ref, watch } from 'vue'
9+
import { getSrc } from './util'
1410
11+
import Box from '../Box/box.vue'
1512
import ViewObserver from '../Misc/view-observer.vue'
1613
import DefaultLoader from './default-loader.vue'
17-
import Box from '../Box/box.vue'
1814
1915
interface BlockImageProps extends /* @vue-ignore */ BoxProps {
2016
src?: string
@@ -29,53 +25,25 @@
2925
loader?: Component
3026
}
3127
32-
const [root, setRoot] = customRef<HTMLElement>()
33-
const rect = useRect(root)
34-
3528
const props = withDefaults(defineProps<BlockImageProps>(), {
3629
fit: 'cover',
3730
position: 'center',
3831
cover: false,
3932
loader: DefaultLoader
4033
})
4134
42-
const image = ref<string>('')
43-
const status = shallowReactive<Status>({
44-
progress: 0,
45-
error: false,
46-
visible: false
47-
})
48-
49-
function resolve() {
50-
assert(rect.ready, 'rect must be ready')
51-
52-
getData(
53-
{
54-
src: props.src,
55-
width: props.width || rect.width,
56-
height: props.height || rect.height
57-
},
58-
image,
59-
status
60-
)
61-
}
35+
const visible = ref(false)
36+
const fetch = useFetch(() => getSrc(props), 'url-blob', { init: false })
6237
6338
watch(
64-
() => rect.ready && status.visible,
39+
visible,
6540
(visible) => {
66-
if (!visible || !props.lazy) return
67-
if (status.progress || status.error || image.value) return
68-
resolve()
69-
}
70-
)
71-
72-
watch(() => props.src, resolve)
73-
watch(
74-
() => rect.ready,
75-
() => !props.lazy && resolve()
41+
if (fetch.ready || fetch.loading || fetch.error) return
42+
if (!props.lazy || visible) fetch.refetch()
43+
},
44+
{ immediate: true }
7645
)
7746
78-
onUnmounted(() => clean(image.value))
7947
defineOptions({ name: 'MdBlockImage' })
8048
</script>
8149

@@ -84,24 +52,23 @@
8452
:as="Box"
8553
offset="50"
8654
class="md-block-image md-image"
87-
:ref="setRoot"
88-
:loading="!image || undefined"
89-
:error="status.error || undefined"
90-
@viewchange="status.visible = $event"
55+
:loading="fetch.loading || undefined"
56+
:error="fetch.error || undefined"
57+
v-model="visible"
9158
>
9259
<div class="md-loader">
9360
<component
9461
:is="loader"
95-
:error="status.error"
96-
:progress="status.progress"
97-
:ready="!!image"
98-
@retry="resolve"
62+
:error="fetch.error"
63+
:progress="fetch.progress"
64+
:ready="fetch.ready"
65+
@retry="fetch.refetch"
9966
/>
10067
</div>
10168
<img
10269
class="md-image-element"
103-
v-if="!status.error"
104-
:src="image"
70+
v-if="!fetch.error"
71+
:src="fetch.data"
10572
:alt
10673
:width
10774
:height

packages/lib/src/components/Image/square-image.vue

Lines changed: 18 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,17 @@
44
import type { Component } from 'vue'
55
import type { BoxProps } from '../Box/util'
66
import type { FrameVariants } from '../Frame/variants'
7-
import type { Status } from './util'
87
9-
import { clean } from '@/utils/object/data'
108
import { createStyle } from '@/utils/create-style'
11-
import { onMounted, onUnmounted, ref, shallowReactive, watch } from 'vue'
9+
import { ref, watch } from 'vue'
1210
import { frames } from '../Frame/variants'
1311
import { toSvgMask } from '../Frame/util'
14-
import { getData } from './util'
12+
import { useFetch } from '@/ref/use-fetch'
1513
1614
import ViewObserver from '../Misc/view-observer.vue'
1715
import DefaultLoader from './default-loader.vue'
1816
import Box from '../Box/box.vue'
17+
import { getSrc } from './util'
1918
2019
interface SquareImageProps /* @vue-ignore */ extends BoxProps {
2120
src?: string
@@ -31,24 +30,8 @@
3130
loader: DefaultLoader
3231
})
3332
34-
const image = ref('')
35-
const status = shallowReactive<Status>({
36-
progress: 0,
37-
error: false,
38-
visible: false
39-
})
40-
41-
function resolve() {
42-
if (!props.src) return
43-
getData(
44-
{
45-
src: props.src,
46-
size: props.size
47-
},
48-
image,
49-
status
50-
)
51-
}
33+
const visible = ref(false)
34+
const fetch = useFetch(() => getSrc(props), 'url-blob', { init: false })
5235
5336
const className = createStyle(() => ({
5437
r: '#xs',
@@ -61,17 +44,13 @@
6144
}))
6245
6346
watch(
64-
() => status.visible,
47+
visible,
6548
(visible) => {
66-
if (!visible || !props.lazy) return
67-
if (status.progress || status.error || image.value) return
68-
resolve()
69-
}
49+
if (fetch.ready || fetch.loading || fetch.error) return
50+
if (!props.lazy || visible) fetch.refetch()
51+
},
52+
{ immediate: true }
7053
)
71-
72-
watch(() => props.src, resolve)
73-
onMounted(() => !props.lazy && resolve())
74-
onUnmounted(() => clean(image.value))
7554
</script>
7655

7756
<template>
@@ -81,22 +60,22 @@
8160
apply="visible"
8261
class="md-square-image md-image"
8362
:class="className"
84-
:loading="!image || undefined"
85-
:error="status.error || undefined"
86-
@viewchange="status.visible = $event"
63+
:loading="!fetch.data || undefined"
64+
:error="fetch.error || undefined"
65+
v-model="visible"
8766
>
8867
<component
8968
class="md-loader"
9069
:is="loader"
91-
:error="status.error"
92-
:progress="status.progress"
93-
:ready="!!image"
94-
@retry="resolve"
70+
:error="fetch.error"
71+
:progress="fetch.progress"
72+
:ready="fetch.ready"
73+
@retry="fetch.refetch"
9574
/>
9675
<img
9776
class="md-image-element"
9877
v-bind="$attrs"
99-
:src="image"
78+
:src="fetch.data"
10079
:width="size"
10180
:height="size"
10281
/>
Lines changed: 5 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,10 @@
1-
import type { Reactive, Ref } from 'vue'
2-
3-
const store: Map<string, Blob> = new Map()
4-
5-
export async function resolveImage(
6-
source: string,
7-
progress: (v: number) => void
8-
): Promise<Blob> {
9-
if (store.has(source)) {
10-
progress(100)
11-
return store.get(source)!
12-
}
13-
14-
progress(Infinity)
15-
16-
const xhr = new XMLHttpRequest()
17-
xhr.responseType = 'blob'
18-
xhr.open('GET', source)
19-
20-
xhr.addEventListener('progress', ({ total, loaded }) => {
21-
progress(total ? Math.floor((loaded / total) * 100) : Infinity)
22-
})
23-
24-
xhr.send()
25-
26-
const data = await new Promise<Blob | void>((resolve) => {
27-
xhr.addEventListener('error', () => resolve())
28-
xhr.addEventListener('load', () => resolve(xhr.response))
29-
})
30-
31-
if (!data) {
32-
throw new Error('Failed to load image')
33-
}
34-
35-
store.set(source, data)
36-
return data
37-
}
38-
39-
type ImageProps = {
40-
width?: number
41-
height?: number
42-
size?: number
1+
type Props = {
432
src?: string
3+
[key: string]: any
444
}
455

46-
export type Status = {
47-
progress: number
48-
error: boolean
49-
visible: boolean
50-
}
51-
52-
export async function getData(
53-
props: ImageProps,
54-
image: Ref<string>,
55-
status: Reactive<Status>
56-
) {
57-
if (!props.src) return
58-
status.error = false
59-
URL.revokeObjectURL(image.value)
60-
image.value = ''
61-
62-
const source = props.src.replaceAll(/\[(\w+)]/g, (match, prop) =>
63-
String((props as any)[prop] || match)
6+
export function getSrc(props: Props): string {
7+
return (props.src ?? '').replaceAll(/\[(\w+)]/g, (match, prop) =>
8+
String(props[prop] || match)
649
)
65-
66-
resolveImage(source, (e) => (status.progress = e))
67-
.then((data) => (image.value = URL.createObjectURL(data)))
68-
.catch(() => (status.error = true))
6910
}

packages/lib/src/components/List/list-item.vue

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,11 @@
152152
:style="{ top: addPX(index * list.size), height: addPX(list.size) }"
153153
>
154154
<div class="md-list-item-wrapper" ref="wrapper" :data-index="index">
155-
<component :value :is="list.component" class="md-list-item-content">
155+
<component
156+
v-bind="props"
157+
:is="list.component"
158+
class="md-list-item-content"
159+
>
156160
{{ label }}
157161
</component>
158162
<div v-if="list.sortable" class="draggable" @pointerdown="sortEvent">
@@ -165,11 +169,11 @@
165169
v-if="item"
166170
v-show="(key === 'left') === isSwipingLeft"
167171
:class="key"
172+
:icon="item.icon"
168173
:style="{
169174
background: item.color,
170175
color: Colors.isLight(item.color) ? '#000' : '#fff'
171176
}"
172-
:icon="item.icon"
173177
/>
174178
</template>
175179
</div>

0 commit comments

Comments
 (0)