@namelivia/vue-components 4.6.0 → 4.8.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namelivia/vue-components",
3
- "version": "4.6.0",
3
+ "version": "4.8.0",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.esm.js",
6
6
  "peerDependencies": {
@@ -0,0 +1,10 @@
1
+ import BanIcon from './BanIcon.vue'
2
+
3
+ describe('<BanIcon />', () => {
4
+ it('renders with default values', () => {
5
+ cy.mount(BanIcon)
6
+ cy.get('svg')
7
+ .should('be.visible')
8
+ .and('have.attr', 'width', '24')
9
+ })
10
+ })
@@ -0,0 +1,24 @@
1
+ import BanIcon from './BanIcon.vue';
2
+
3
+ export default {
4
+ title: 'Icons/BanIcon',
5
+ component: BanIcon,
6
+ argTypes: {
7
+ size: { control: { type: 'range', min: 12, max: 100, step: 1 } },
8
+ color: { control: 'color' },
9
+ },
10
+ };
11
+
12
+ export const Default = {
13
+ args: {
14
+ size: 24,
15
+ color: '#000000',
16
+ },
17
+ render: (args) => ({
18
+ components: { BanIcon },
19
+ setup() {
20
+ return { args };
21
+ },
22
+ template: '<BanIcon v-bind="args" />',
23
+ }),
24
+ };
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-ban-icon lucide-ban"><path d="M4.929 4.929 19.07 19.071"/><circle cx="12" cy="12" r="10"/></svg>
3
+ </template>
4
+
5
+ <script setup>
6
+ defineProps({
7
+ size: {
8
+ type: [Number, String],
9
+ default: 24
10
+ },
11
+ color: {
12
+ type: String,
13
+ default: 'currentColor'
14
+ }
15
+ });
16
+ </script>
@@ -0,0 +1,10 @@
1
+ import BasketIcon from './BasketIcon.vue'
2
+
3
+ describe('<BasketIcon />', () => {
4
+ it('renders with default values', () => {
5
+ cy.mount(BasketIcon)
6
+ cy.get('svg')
7
+ .should('be.visible')
8
+ .and('have.attr', 'width', '24')
9
+ })
10
+ })
@@ -0,0 +1,24 @@
1
+ import BasketIcon from './BasketIcon.vue';
2
+
3
+ export default {
4
+ title: 'Icons/BasketIcon',
5
+ component: BasketIcon,
6
+ argTypes: {
7
+ size: { control: { type: 'range', min: 12, max: 100, step: 1 } },
8
+ color: { control: 'color' },
9
+ },
10
+ };
11
+
12
+ export const Default = {
13
+ args: {
14
+ size: 24,
15
+ color: '#000000',
16
+ },
17
+ render: (args) => ({
18
+ components: { BasketIcon },
19
+ setup() {
20
+ return { args };
21
+ },
22
+ template: '<BasketIcon v-bind="args" />',
23
+ }),
24
+ };
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-shopping-basket-icon lucide-shopping-basket"><path d="m15 11-1 9"/><path d="m19 11-4-7"/><path d="M2 11h20"/><path d="m3.5 11 1.6 7.4a2 2 0 0 0 2 1.6h9.8a2 2 0 0 0 2-1.6l1.7-7.4"/><path d="M4.5 15.5h15"/><path d="m5 11 4-7"/><path d="m9 11 1 9"/></svg>
3
+ </template>
4
+
5
+ <script setup>
6
+ defineProps({
7
+ size: {
8
+ type: [Number, String],
9
+ default: 24
10
+ },
11
+ color: {
12
+ type: String,
13
+ default: 'currentColor'
14
+ }
15
+ });
16
+ </script>
@@ -0,0 +1,10 @@
1
+ import ShirtIcon from './ShirtIcon.vue'
2
+
3
+ describe('<ShirtIcon />', () => {
4
+ it('renders with default values', () => {
5
+ cy.mount(ShirtIcon)
6
+ cy.get('svg')
7
+ .should('be.visible')
8
+ .and('have.attr', 'width', '24')
9
+ })
10
+ })
@@ -0,0 +1,24 @@
1
+ import ShirtIcon from './ShirtIcon.vue';
2
+
3
+ export default {
4
+ title: 'Icons/ShirtIcon',
5
+ component: ShirtIcon,
6
+ argTypes: {
7
+ size: { control: { type: 'range', min: 12, max: 100, step: 1 } },
8
+ color: { control: 'color' },
9
+ },
10
+ };
11
+
12
+ export const Default = {
13
+ args: {
14
+ size: 24,
15
+ color: '#000000',
16
+ },
17
+ render: (args) => ({
18
+ components: { ShirtIcon },
19
+ setup() {
20
+ return { args };
21
+ },
22
+ template: '<ShirtIcon v-bind="args" />',
23
+ }),
24
+ };
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-shirt-icon lucide-shirt"><path d="M20.38 3.46 16 2a4 4 0 0 1-8 0L3.62 3.46a2 2 0 0 0-1.34 2.23l.58 3.47a1 1 0 0 0 .99.84H6v10c0 1.1.9 2 2 2h8a2 2 0 0 0 2-2V10h2.15a1 1 0 0 0 .99-.84l.58-3.47a2 2 0 0 0-1.34-2.23z"/></svg>
3
+ </template>
4
+
5
+ <script setup>
6
+ defineProps({
7
+ size: {
8
+ type: [Number, String],
9
+ default: 24
10
+ },
11
+ color: {
12
+ type: String,
13
+ default: 'currentColor'
14
+ }
15
+ });
16
+ </script>
@@ -0,0 +1,10 @@
1
+ import ThrashIcon from './ThrashIcon.vue'
2
+
3
+ describe('<ThrashIcon />', () => {
4
+ it('renders with default values', () => {
5
+ cy.mount(ThrashIcon)
6
+ cy.get('svg')
7
+ .should('be.visible')
8
+ .and('have.attr', 'width', '24')
9
+ })
10
+ })
@@ -0,0 +1,24 @@
1
+ import ThrashIcon from './ThrashIcon.vue';
2
+
3
+ export default {
4
+ title: 'Icons/ThrashIcon',
5
+ component: ThrashIcon,
6
+ argTypes: {
7
+ size: { control: { type: 'range', min: 12, max: 100, step: 1 } },
8
+ color: { control: 'color' },
9
+ },
10
+ };
11
+
12
+ export const Default = {
13
+ args: {
14
+ size: 24,
15
+ color: '#000000',
16
+ },
17
+ render: (args) => ({
18
+ components: { ThrashIcon },
19
+ setup() {
20
+ return { args };
21
+ },
22
+ template: '<ThrashIcon v-bind="args" />',
23
+ }),
24
+ };
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-trash2-icon lucide-trash-2"><path d="M10 11v6"/><path d="M14 11v6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>
3
+ </template>
4
+
5
+ <script setup>
6
+ defineProps({
7
+ size: {
8
+ type: [Number, String],
9
+ default: 24
10
+ },
11
+ color: {
12
+ type: String,
13
+ default: 'currentColor'
14
+ }
15
+ });
16
+ </script>
@@ -0,0 +1,10 @@
1
+ import WashingMachineIcon from './WashingMachineIcon.vue'
2
+
3
+ describe('<WashingMachineIcon />', () => {
4
+ it('renders with default values', () => {
5
+ cy.mount(WashingMachineIcon)
6
+ cy.get('svg')
7
+ .should('be.visible')
8
+ .and('have.attr', 'width', '24')
9
+ })
10
+ })
@@ -0,0 +1,24 @@
1
+ import WashingMachineIcon from './WashingMachineIcon.vue';
2
+
3
+ export default {
4
+ title: 'Icons/WashingMachineIcon',
5
+ component: WashingMachineIcon,
6
+ argTypes: {
7
+ size: { control: { type: 'range', min: 12, max: 100, step: 1 } },
8
+ color: { control: 'color' },
9
+ },
10
+ };
11
+
12
+ export const Default = {
13
+ args: {
14
+ size: 24,
15
+ color: '#000000',
16
+ },
17
+ render: (args) => ({
18
+ components: { WashingMachineIcon },
19
+ setup() {
20
+ return { args };
21
+ },
22
+ template: '<WashingMachineIcon v-bind="args" />',
23
+ }),
24
+ };
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-washing-machine-icon lucide-washing-machine"><path d="M3 6h3"/><path d="M17 6h.01"/><rect width="18" height="20" x="3" y="2" rx="2"/><circle cx="12" cy="13" r="5"/><path d="M12 18a2.5 2.5 0 0 0 0-5 2.5 2.5 0 0 1 0-5"/></svg>
3
+ </template>
4
+
5
+ <script setup>
6
+ defineProps({
7
+ size: {
8
+ type: [Number, String],
9
+ default: 24
10
+ },
11
+ color: {
12
+ type: String,
13
+ default: 'currentColor'
14
+ }
15
+ });
16
+ </script>
@@ -0,0 +1,7 @@
1
+ import InfiniteScroll from './InfiniteScroll.vue'
2
+
3
+ describe('<InfiniteScroll />', () => {
4
+ it.skip('emits load-more event when sentinel is visible', () => {
5
+ // TODO
6
+ })
7
+ })
@@ -0,0 +1,38 @@
1
+ import InfiniteScroll from './InfiniteScroll.vue';
2
+ import Card from '../Card/Card.vue';
3
+ import { ref } from 'vue';
4
+
5
+ export default {
6
+ title: 'Components/InfiniteScroll',
7
+ component: InfiniteScroll,
8
+ };
9
+
10
+ export const Default = {
11
+ render: (args) => ({
12
+ components: { InfiniteScroll, Card },
13
+ setup() {
14
+ const items = ref([1, 2, 3, 4, 5]);
15
+ const loadMore = () => {
16
+ const last = items.value[items.value.length - 1];
17
+ // Simulate API delay
18
+ setTimeout(() => {
19
+ for (let i = 1; i <= 5; i++) {
20
+ items.value.push(last + i);
21
+ }
22
+ }, 500);
23
+ };
24
+ return { args, items, loadMore };
25
+ },
26
+ template: `
27
+ <div style="height: 400px; overflow-y: auto; border: 1px solid #ccc;">
28
+ <InfiniteScroll v-bind="args" @load-more="loadMore">
29
+ <div v-for="item in items" :key="item" style="padding: 20px; border-bottom: 1px solid #eee;">
30
+ <Card :title="'Item ' + item">
31
+ <p>Scroll down to load more content...</p>
32
+ </Card>
33
+ </div>
34
+ </InfiniteScroll>
35
+ </div>
36
+ `,
37
+ }),
38
+ };
@@ -0,0 +1,59 @@
1
+ <template lang="pug">
2
+ div(class="infinite-scroll-container")
3
+ slot
4
+ div(ref="sentinel" class="sentinel")
5
+ </template>
6
+
7
+ <script setup>
8
+ import { ref, onMounted, onBeforeUnmount } from 'vue';
9
+
10
+ const props = defineProps({
11
+ threshold: {
12
+ type: Number,
13
+ default: 0.1
14
+ },
15
+ rootMargin: {
16
+ type: String,
17
+ default: '0px'
18
+ },
19
+ disabled: {
20
+ type: Boolean,
21
+ default: false
22
+ }
23
+ });
24
+
25
+ const emit = defineEmits(['load-more']);
26
+ const sentinel = ref(null);
27
+ let observer = null;
28
+
29
+ onMounted(() => {
30
+ observer = new IntersectionObserver(([entry]) => {
31
+ if (entry.isIntersecting && !props.disabled) {
32
+ emit('load-more');
33
+ }
34
+ }, {
35
+ rootMargin: props.rootMargin,
36
+ threshold: props.threshold
37
+ });
38
+
39
+ if (sentinel.value) {
40
+ observer.observe(sentinel.value);
41
+ }
42
+ });
43
+
44
+ onBeforeUnmount(() => {
45
+ if (observer) {
46
+ observer.disconnect();
47
+ }
48
+ });
49
+ </script>
50
+
51
+ <style scoped>
52
+ .infinite-scroll-container {
53
+ width: 100%;
54
+ }
55
+ .sentinel {
56
+ height: var(--infinite-scroll-sentinel-height, 1px);
57
+ width: 100%;
58
+ }
59
+ </style>
package/src/index.js CHANGED
@@ -29,3 +29,4 @@ export { default as SkullIcon } from './Icons/SkullIcon/SkullIcon.vue'
29
29
  export { default as CalendarIcon } from './Icons/CalendarIcon/CalendarIcon.vue'
30
30
  export { default as SaveIcon } from './Icons/SaveIcon/SaveIcon.vue'
31
31
  export { default as CreateIcon } from './Icons/CreateIcon/CreateIcon.vue'
32
+ export { default as InfiniteScroll } from './InfiniteScroll/InfiniteScroll.vue'
package/styles/index.css CHANGED
@@ -109,6 +109,8 @@
109
109
  --color-navbar-current-background: hsl(210, 80%, 23%);
110
110
  --color-navbar-link-background: hsl(210, 50%, 23%);
111
111
  --font-size-navbar: 0.875rem;
112
+ /* INFINITE SCROLL */
113
+ --infinite-scroll-sentinel-height: 1px;
112
114
  }
113
115
 
114
116
  .one-theme{