@lasterp/shared 1.0.0-alpha.9 → 1.0.0-beta.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/dist/node/index.d.ts +129 -73
- package/dist/node/index.js +109 -3
- package/dist/rn/index.d.ts +129 -73
- package/dist/rn/index.js +109 -3
- package/package.json +2 -2
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -7
package/dist/node/index.d.ts
CHANGED
|
@@ -1,28 +1,101 @@
|
|
|
1
1
|
interface Item {
|
|
2
|
-
|
|
2
|
+
item_code: string;
|
|
3
3
|
area: string;
|
|
4
4
|
model: string;
|
|
5
5
|
region: string;
|
|
6
6
|
grade: string;
|
|
7
|
-
|
|
7
|
+
grade_issuer: string;
|
|
8
8
|
color: string;
|
|
9
9
|
storage: string;
|
|
10
10
|
memory: string;
|
|
11
11
|
connectivity: string;
|
|
12
|
-
|
|
12
|
+
carrier_compatibility: string;
|
|
13
13
|
}
|
|
14
14
|
interface ItemVariant extends Item {
|
|
15
|
-
|
|
15
|
+
item_variant: string;
|
|
16
16
|
}
|
|
17
17
|
interface Model {
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
model_number: string;
|
|
19
|
+
sim_card_type: string;
|
|
20
20
|
connectivity: string;
|
|
21
21
|
}
|
|
22
22
|
interface Colour {
|
|
23
23
|
color: string;
|
|
24
24
|
hex: string;
|
|
25
|
-
|
|
25
|
+
color_system: string;
|
|
26
|
+
}
|
|
27
|
+
interface Globals {
|
|
28
|
+
header: Header;
|
|
29
|
+
footer: Footer;
|
|
30
|
+
}
|
|
31
|
+
interface Brand {
|
|
32
|
+
brandImage?: string;
|
|
33
|
+
}
|
|
34
|
+
interface NavbarItem {
|
|
35
|
+
label: string;
|
|
36
|
+
enableDropdown: boolean;
|
|
37
|
+
enableLink: boolean;
|
|
38
|
+
link?: string;
|
|
39
|
+
dropdownDescription?: string;
|
|
40
|
+
dropdownCTALabel?: string;
|
|
41
|
+
dropdownCTALink?: string;
|
|
42
|
+
groups?: NavbarSubItemGroup[];
|
|
43
|
+
}
|
|
44
|
+
interface NavbarSubItemGroup {
|
|
45
|
+
title: string;
|
|
46
|
+
items: NavbarSubItem[];
|
|
47
|
+
}
|
|
48
|
+
interface NavbarSubItem {
|
|
49
|
+
label: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
image?: string;
|
|
52
|
+
link?: string;
|
|
53
|
+
}
|
|
54
|
+
interface Topbar {
|
|
55
|
+
enabled: boolean;
|
|
56
|
+
layout: string;
|
|
57
|
+
items: TopbarItem[];
|
|
58
|
+
}
|
|
59
|
+
interface TopbarItem {
|
|
60
|
+
icon?: string;
|
|
61
|
+
label: string;
|
|
62
|
+
link?: string;
|
|
63
|
+
}
|
|
64
|
+
interface Header {
|
|
65
|
+
headerType?: string;
|
|
66
|
+
brand: Brand;
|
|
67
|
+
tabs: NavbarItem[];
|
|
68
|
+
topbar: Topbar;
|
|
69
|
+
}
|
|
70
|
+
interface FooterItemGroup {
|
|
71
|
+
title: string;
|
|
72
|
+
items: FooterItem[];
|
|
73
|
+
}
|
|
74
|
+
interface FooterItem {
|
|
75
|
+
label: string;
|
|
76
|
+
link?: string;
|
|
77
|
+
}
|
|
78
|
+
interface Footer {
|
|
79
|
+
footerType?: string;
|
|
80
|
+
groups: FooterItemGroup[];
|
|
81
|
+
copyright?: string;
|
|
82
|
+
address?: string;
|
|
83
|
+
country?: string;
|
|
84
|
+
phone?: string;
|
|
85
|
+
email?: string;
|
|
86
|
+
}
|
|
87
|
+
interface Hero {
|
|
88
|
+
type: string;
|
|
89
|
+
data: Record<string, unknown>;
|
|
90
|
+
}
|
|
91
|
+
interface Block {
|
|
92
|
+
type: string;
|
|
93
|
+
data: Record<string, unknown>;
|
|
94
|
+
}
|
|
95
|
+
interface Page {
|
|
96
|
+
slug: string;
|
|
97
|
+
hero?: Hero;
|
|
98
|
+
blocks: Block[];
|
|
26
99
|
}
|
|
27
100
|
import { FrappeApp, FrappeAuth, FrappeCall } from "frappe-js-sdk";
|
|
28
101
|
import { FrappeDB } from "frappe-js-sdk/lib/db";
|
|
@@ -513,79 +586,62 @@ declare const useFrappeUpdateDoc: <T = any>() => {
|
|
|
513
586
|
isCompleted: boolean;
|
|
514
587
|
reset: () => void;
|
|
515
588
|
};
|
|
516
|
-
interface
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
enableLink: boolean;
|
|
527
|
-
link?: string;
|
|
528
|
-
dropdownDescription?: string;
|
|
529
|
-
dropdownCTALabel?: string;
|
|
530
|
-
dropdownCTALink?: string;
|
|
531
|
-
groups?: NavbarSubItemGroup[];
|
|
532
|
-
}
|
|
533
|
-
interface NavbarSubItemGroup {
|
|
534
|
-
title: string;
|
|
535
|
-
items: NavbarSubItem[];
|
|
536
|
-
}
|
|
537
|
-
interface NavbarSubItem {
|
|
538
|
-
label: string;
|
|
539
|
-
description?: string;
|
|
540
|
-
image?: string;
|
|
541
|
-
link?: string;
|
|
589
|
+
interface VariantSelectorProps<T extends {
|
|
590
|
+
id: string;
|
|
591
|
+
specs: Record<string, string>;
|
|
592
|
+
}> {
|
|
593
|
+
variants: T[];
|
|
594
|
+
attributes: {
|
|
595
|
+
key: string;
|
|
596
|
+
values: string[];
|
|
597
|
+
}[];
|
|
598
|
+
defaultId?: string;
|
|
542
599
|
}
|
|
543
|
-
interface
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
}
|
|
548
|
-
interface TopbarItem {
|
|
549
|
-
icon?: string;
|
|
550
|
-
label: string;
|
|
551
|
-
link?: string;
|
|
552
|
-
}
|
|
553
|
-
interface Header {
|
|
554
|
-
headerType?: string;
|
|
555
|
-
brand: Brand;
|
|
556
|
-
tabs: NavbarItem[];
|
|
557
|
-
topbar: Topbar;
|
|
600
|
+
interface VariantSelectorOption {
|
|
601
|
+
key: string;
|
|
602
|
+
value: string;
|
|
603
|
+
state: "selected" | "available" | "unavailable";
|
|
558
604
|
}
|
|
559
|
-
interface
|
|
560
|
-
|
|
561
|
-
|
|
605
|
+
interface VariantSelectorResult {
|
|
606
|
+
variantId?: string;
|
|
607
|
+
onOptionSelect: (key: string, value: string) => void;
|
|
608
|
+
getOptions: (key: string) => VariantSelectorOption[];
|
|
562
609
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
610
|
+
declare const useVariantSelector: <T extends {
|
|
611
|
+
id: string;
|
|
612
|
+
specs: Record<string, string>;
|
|
613
|
+
}>(props: VariantSelectorProps<T>) => VariantSelectorResult;
|
|
614
|
+
interface Category {
|
|
615
|
+
name: string;
|
|
566
616
|
}
|
|
567
|
-
interface
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
country?: string;
|
|
573
|
-
phone?: string;
|
|
574
|
-
email?: string;
|
|
617
|
+
interface Product {
|
|
618
|
+
name: string;
|
|
619
|
+
image: string;
|
|
620
|
+
item_code: string;
|
|
621
|
+
description: string;
|
|
575
622
|
}
|
|
576
|
-
interface
|
|
577
|
-
|
|
578
|
-
|
|
623
|
+
interface ProductVariant extends ItemVariant {
|
|
624
|
+
name: string;
|
|
625
|
+
currency: string;
|
|
626
|
+
rate: number;
|
|
627
|
+
qty: number;
|
|
628
|
+
images: string[];
|
|
629
|
+
specs: Record<string, string>;
|
|
579
630
|
}
|
|
580
|
-
interface
|
|
581
|
-
|
|
582
|
-
|
|
631
|
+
interface ShopContext {
|
|
632
|
+
categories: Category[];
|
|
633
|
+
grades: string[];
|
|
634
|
+
selected_category?: Category;
|
|
635
|
+
selected_grade?: string;
|
|
636
|
+
products: Product[];
|
|
583
637
|
}
|
|
584
|
-
interface
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
638
|
+
interface ProductContext {
|
|
639
|
+
product: Product;
|
|
640
|
+
specs: Record<string, string[]>;
|
|
641
|
+
variants: ProductVariant[];
|
|
642
|
+
models: Record<string, Model>;
|
|
643
|
+
colors: Record<string, Colour>;
|
|
588
644
|
}
|
|
589
645
|
import { camelize, decamelize, camelizeKeys, decamelizeKeys } from "humps";
|
|
590
646
|
declare function equalsIgnoreCase(str1: string, str2: string): boolean;
|
|
591
|
-
export { useSearch, useFrappeUpdateDoc, useFrappePutCall, useFrappePrefetchDoc, useFrappePostCall, useFrappeGetDocList, useFrappeGetDocCount, useFrappeGetDoc, useFrappeGetCall, useFrappeFileUpload, useFrappeEventListener, useFrappeDocumentEventListener, useFrappeDocTypeEventListener, useFrappeDeleteDoc, useFrappeDeleteCall, useFrappeCreateDoc, useFrappeAuth, equalsIgnoreCase, decamelizeKeys, decamelize, camelizeKeys, camelize, ViewerEventData, UseFrappeFileUploadReturnType, TopbarItem, Topbar, TokenParams, SearchResult, Page, NavbarSubItemGroup, NavbarSubItem, NavbarItem, Model, ItemVariant, Item, Hero, Header, Globals, FrappeProviderProps, FrappeProvider, FrappeMutationResult, FrappeFileUploadResponse, FrappeError, FrappeContext, FrappeConfig, FooterItemGroup, FooterItem, Footer, DocumentUpdateEventData, DocTypeListUpdateEventData, Colour, Brand, Block };
|
|
647
|
+
export { useVariantSelector, useSearch, useFrappeUpdateDoc, useFrappePutCall, useFrappePrefetchDoc, useFrappePostCall, useFrappeGetDocList, useFrappeGetDocCount, useFrappeGetDoc, useFrappeGetCall, useFrappeFileUpload, useFrappeEventListener, useFrappeDocumentEventListener, useFrappeDocTypeEventListener, useFrappeDeleteDoc, useFrappeDeleteCall, useFrappeCreateDoc, useFrappeAuth, equalsIgnoreCase, decamelizeKeys, decamelize, camelizeKeys, camelize, ViewerEventData, VariantSelectorResult, VariantSelectorProps, VariantSelectorOption, UseFrappeFileUploadReturnType, TopbarItem, Topbar, TokenParams, ShopContext, SearchResult, ProductVariant, ProductContext, Product, Page, NavbarSubItemGroup, NavbarSubItem, NavbarItem, Model, ItemVariant, Item, Hero, Header, Globals, FrappeProviderProps, FrappeProvider, FrappeMutationResult, FrappeFileUploadResponse, FrappeError, FrappeContext, FrappeConfig, FooterItemGroup, FooterItem, Footer, DocumentUpdateEventData, DocTypeListUpdateEventData, Colour, Category, Brand, Block };
|
package/dist/node/index.js
CHANGED
|
@@ -46,7 +46,7 @@ class SocketIO {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
// src/frappe/provider.tsx
|
|
49
|
-
import {
|
|
49
|
+
import { jsx } from "react/jsx-runtime";
|
|
50
50
|
|
|
51
51
|
var FrappeContext = createContext(null);
|
|
52
52
|
var FrappeProvider = ({
|
|
@@ -71,10 +71,10 @@ var FrappeProvider = ({
|
|
|
71
71
|
socket: enableSocket ? new SocketIO(url, siteName, socketPort, tokenParams).socket : undefined
|
|
72
72
|
};
|
|
73
73
|
}, [url, tokenParams, enableSocket, socketPort, siteName, customHeaders]);
|
|
74
|
-
return /* @__PURE__ */
|
|
74
|
+
return /* @__PURE__ */ jsx(FrappeContext.Provider, {
|
|
75
75
|
value: frappeConfig,
|
|
76
76
|
children
|
|
77
|
-
}
|
|
77
|
+
});
|
|
78
78
|
};
|
|
79
79
|
// src/frappe/hooks/auth.ts
|
|
80
80
|
import { useCallback, useContext, useState, useEffect } from "react";
|
|
@@ -465,12 +465,118 @@ var useFrappeUpdateDoc = () => {
|
|
|
465
465
|
reset
|
|
466
466
|
};
|
|
467
467
|
};
|
|
468
|
+
// src/hooks/use-variant-selector/hook.ts
|
|
469
|
+
import { useCallback as useCallback4, useMemo as useMemo2, useState as useState5 } from "react";
|
|
470
|
+
|
|
471
|
+
// src/hooks/use-variant-selector/utils.ts
|
|
472
|
+
function findVariant(variants, specs, caseInsensitive) {
|
|
473
|
+
return variants.find((variant) => {
|
|
474
|
+
return Object.entries(specs).every(([key, value]) => {
|
|
475
|
+
const vv = variant.specs[key];
|
|
476
|
+
if (!vv)
|
|
477
|
+
return false;
|
|
478
|
+
if (caseInsensitive) {
|
|
479
|
+
return vv.toLowerCase() === value.toLowerCase();
|
|
480
|
+
}
|
|
481
|
+
return vv === value;
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
function findVariants(variants, specs, caseInsensitive) {
|
|
486
|
+
return variants.filter((variant) => {
|
|
487
|
+
return Object.entries(specs).every(([key, value]) => {
|
|
488
|
+
const vv = variant.specs[key];
|
|
489
|
+
if (!vv)
|
|
490
|
+
return false;
|
|
491
|
+
if (caseInsensitive) {
|
|
492
|
+
return vv.toLowerCase() === value.toLowerCase();
|
|
493
|
+
}
|
|
494
|
+
return vv === value;
|
|
495
|
+
});
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// src/hooks/use-variant-selector/hook.ts
|
|
500
|
+
var useVariantSelector = (props) => {
|
|
501
|
+
const { variants, attributes, defaultId } = props;
|
|
502
|
+
const [selectedSpecs, setSelectedSpecs] = useState5(() => {
|
|
503
|
+
if (defaultId) {
|
|
504
|
+
const variant = variants.find((v) => v.id === defaultId);
|
|
505
|
+
return variant?.specs || {};
|
|
506
|
+
}
|
|
507
|
+
return {};
|
|
508
|
+
});
|
|
509
|
+
const variantId = useMemo2(() => {
|
|
510
|
+
const complete = attributes.every((attr) => selectedSpecs[attr.key]);
|
|
511
|
+
if (!complete)
|
|
512
|
+
return;
|
|
513
|
+
const variant = findVariant(variants, selectedSpecs);
|
|
514
|
+
return variant?.id;
|
|
515
|
+
}, [variants, selectedSpecs, attributes]);
|
|
516
|
+
const options = useMemo2(() => {
|
|
517
|
+
const result = {};
|
|
518
|
+
attributes.forEach((attr, attrIndex) => {
|
|
519
|
+
const constraints = {};
|
|
520
|
+
for (let i = 0;i < attrIndex; i++) {
|
|
521
|
+
const key = attributes[i]?.key;
|
|
522
|
+
if (key && selectedSpecs[key])
|
|
523
|
+
constraints[key] = selectedSpecs[key];
|
|
524
|
+
}
|
|
525
|
+
const matchingVariants = findVariants(variants, constraints);
|
|
526
|
+
const availableValues = new Set(matchingVariants.map((v) => v.specs[attr.key]));
|
|
527
|
+
result[attr.key] = attr.values.map((value) => {
|
|
528
|
+
const isSelected = selectedSpecs[attr.key] === value;
|
|
529
|
+
const isAvailable = availableValues.has(value);
|
|
530
|
+
return {
|
|
531
|
+
key: attr.key,
|
|
532
|
+
value,
|
|
533
|
+
state: isSelected ? "selected" : isAvailable ? "available" : "unavailable"
|
|
534
|
+
};
|
|
535
|
+
});
|
|
536
|
+
});
|
|
537
|
+
return result;
|
|
538
|
+
}, [variants, attributes, selectedSpecs]);
|
|
539
|
+
const onOptionSelect = useCallback4((key, value) => {
|
|
540
|
+
setSelectedSpecs((prev) => {
|
|
541
|
+
const newSpecs = { ...prev, [key]: value };
|
|
542
|
+
const attrIndex = attributes.findIndex((a) => a.key === key);
|
|
543
|
+
for (let i = attrIndex + 1;i < attributes.length; i++) {
|
|
544
|
+
const downstreamAttr = attributes[i];
|
|
545
|
+
if (!downstreamAttr)
|
|
546
|
+
continue;
|
|
547
|
+
const constraints = {};
|
|
548
|
+
for (let j = 0;j < i; j++) {
|
|
549
|
+
const k = attributes[j]?.key;
|
|
550
|
+
if (k && newSpecs[k])
|
|
551
|
+
constraints[k] = newSpecs[k];
|
|
552
|
+
}
|
|
553
|
+
const matching = findVariants(variants, constraints);
|
|
554
|
+
const availableValues = new Set(matching.map((v) => v.specs[downstreamAttr.key]));
|
|
555
|
+
if (!availableValues.has(newSpecs[downstreamAttr.key])) {
|
|
556
|
+
const firstAvailable = downstreamAttr.values.find((v) => availableValues.has(v));
|
|
557
|
+
if (firstAvailable) {
|
|
558
|
+
newSpecs[downstreamAttr.key] = firstAvailable;
|
|
559
|
+
} else {
|
|
560
|
+
delete newSpecs[downstreamAttr.key];
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
return newSpecs;
|
|
565
|
+
});
|
|
566
|
+
}, [attributes, variants]);
|
|
567
|
+
return {
|
|
568
|
+
variantId,
|
|
569
|
+
onOptionSelect,
|
|
570
|
+
getOptions: (key) => options[key] || []
|
|
571
|
+
};
|
|
572
|
+
};
|
|
468
573
|
// src/utils/char.ts
|
|
469
574
|
import { camelize, decamelize, camelizeKeys, decamelizeKeys } from "humps";
|
|
470
575
|
function equalsIgnoreCase(str1, str2) {
|
|
471
576
|
return str1.localeCompare(str2, undefined, { sensitivity: "accent" }) === 0;
|
|
472
577
|
}
|
|
473
578
|
export {
|
|
579
|
+
useVariantSelector,
|
|
474
580
|
useSearch,
|
|
475
581
|
useFrappeUpdateDoc,
|
|
476
582
|
useFrappePutCall,
|
package/dist/rn/index.d.ts
CHANGED
|
@@ -1,28 +1,101 @@
|
|
|
1
1
|
interface Item {
|
|
2
|
-
|
|
2
|
+
item_code: string;
|
|
3
3
|
area: string;
|
|
4
4
|
model: string;
|
|
5
5
|
region: string;
|
|
6
6
|
grade: string;
|
|
7
|
-
|
|
7
|
+
grade_issuer: string;
|
|
8
8
|
color: string;
|
|
9
9
|
storage: string;
|
|
10
10
|
memory: string;
|
|
11
11
|
connectivity: string;
|
|
12
|
-
|
|
12
|
+
carrier_compatibility: string;
|
|
13
13
|
}
|
|
14
14
|
interface ItemVariant extends Item {
|
|
15
|
-
|
|
15
|
+
item_variant: string;
|
|
16
16
|
}
|
|
17
17
|
interface Model {
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
model_number: string;
|
|
19
|
+
sim_card_type: string;
|
|
20
20
|
connectivity: string;
|
|
21
21
|
}
|
|
22
22
|
interface Colour {
|
|
23
23
|
color: string;
|
|
24
24
|
hex: string;
|
|
25
|
-
|
|
25
|
+
color_system: string;
|
|
26
|
+
}
|
|
27
|
+
interface Globals {
|
|
28
|
+
header: Header;
|
|
29
|
+
footer: Footer;
|
|
30
|
+
}
|
|
31
|
+
interface Brand {
|
|
32
|
+
brandImage?: string;
|
|
33
|
+
}
|
|
34
|
+
interface NavbarItem {
|
|
35
|
+
label: string;
|
|
36
|
+
enableDropdown: boolean;
|
|
37
|
+
enableLink: boolean;
|
|
38
|
+
link?: string;
|
|
39
|
+
dropdownDescription?: string;
|
|
40
|
+
dropdownCTALabel?: string;
|
|
41
|
+
dropdownCTALink?: string;
|
|
42
|
+
groups?: NavbarSubItemGroup[];
|
|
43
|
+
}
|
|
44
|
+
interface NavbarSubItemGroup {
|
|
45
|
+
title: string;
|
|
46
|
+
items: NavbarSubItem[];
|
|
47
|
+
}
|
|
48
|
+
interface NavbarSubItem {
|
|
49
|
+
label: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
image?: string;
|
|
52
|
+
link?: string;
|
|
53
|
+
}
|
|
54
|
+
interface Topbar {
|
|
55
|
+
enabled: boolean;
|
|
56
|
+
layout: string;
|
|
57
|
+
items: TopbarItem[];
|
|
58
|
+
}
|
|
59
|
+
interface TopbarItem {
|
|
60
|
+
icon?: string;
|
|
61
|
+
label: string;
|
|
62
|
+
link?: string;
|
|
63
|
+
}
|
|
64
|
+
interface Header {
|
|
65
|
+
headerType?: string;
|
|
66
|
+
brand: Brand;
|
|
67
|
+
tabs: NavbarItem[];
|
|
68
|
+
topbar: Topbar;
|
|
69
|
+
}
|
|
70
|
+
interface FooterItemGroup {
|
|
71
|
+
title: string;
|
|
72
|
+
items: FooterItem[];
|
|
73
|
+
}
|
|
74
|
+
interface FooterItem {
|
|
75
|
+
label: string;
|
|
76
|
+
link?: string;
|
|
77
|
+
}
|
|
78
|
+
interface Footer {
|
|
79
|
+
footerType?: string;
|
|
80
|
+
groups: FooterItemGroup[];
|
|
81
|
+
copyright?: string;
|
|
82
|
+
address?: string;
|
|
83
|
+
country?: string;
|
|
84
|
+
phone?: string;
|
|
85
|
+
email?: string;
|
|
86
|
+
}
|
|
87
|
+
interface Hero {
|
|
88
|
+
type: string;
|
|
89
|
+
data: Record<string, unknown>;
|
|
90
|
+
}
|
|
91
|
+
interface Block {
|
|
92
|
+
type: string;
|
|
93
|
+
data: Record<string, unknown>;
|
|
94
|
+
}
|
|
95
|
+
interface Page {
|
|
96
|
+
slug: string;
|
|
97
|
+
hero?: Hero;
|
|
98
|
+
blocks: Block[];
|
|
26
99
|
}
|
|
27
100
|
import { FrappeApp, FrappeAuth, FrappeCall } from "frappe-js-sdk";
|
|
28
101
|
import { FrappeDB } from "frappe-js-sdk/lib/db";
|
|
@@ -513,79 +586,62 @@ declare const useFrappeUpdateDoc: <T = any>() => {
|
|
|
513
586
|
isCompleted: boolean;
|
|
514
587
|
reset: () => void;
|
|
515
588
|
};
|
|
516
|
-
interface
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
enableLink: boolean;
|
|
527
|
-
link?: string;
|
|
528
|
-
dropdownDescription?: string;
|
|
529
|
-
dropdownCTALabel?: string;
|
|
530
|
-
dropdownCTALink?: string;
|
|
531
|
-
groups?: NavbarSubItemGroup[];
|
|
532
|
-
}
|
|
533
|
-
interface NavbarSubItemGroup {
|
|
534
|
-
title: string;
|
|
535
|
-
items: NavbarSubItem[];
|
|
536
|
-
}
|
|
537
|
-
interface NavbarSubItem {
|
|
538
|
-
label: string;
|
|
539
|
-
description?: string;
|
|
540
|
-
image?: string;
|
|
541
|
-
link?: string;
|
|
589
|
+
interface VariantSelectorProps<T extends {
|
|
590
|
+
id: string;
|
|
591
|
+
specs: Record<string, string>;
|
|
592
|
+
}> {
|
|
593
|
+
variants: T[];
|
|
594
|
+
attributes: {
|
|
595
|
+
key: string;
|
|
596
|
+
values: string[];
|
|
597
|
+
}[];
|
|
598
|
+
defaultId?: string;
|
|
542
599
|
}
|
|
543
|
-
interface
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
}
|
|
548
|
-
interface TopbarItem {
|
|
549
|
-
icon?: string;
|
|
550
|
-
label: string;
|
|
551
|
-
link?: string;
|
|
552
|
-
}
|
|
553
|
-
interface Header {
|
|
554
|
-
headerType?: string;
|
|
555
|
-
brand: Brand;
|
|
556
|
-
tabs: NavbarItem[];
|
|
557
|
-
topbar: Topbar;
|
|
600
|
+
interface VariantSelectorOption {
|
|
601
|
+
key: string;
|
|
602
|
+
value: string;
|
|
603
|
+
state: "selected" | "available" | "unavailable";
|
|
558
604
|
}
|
|
559
|
-
interface
|
|
560
|
-
|
|
561
|
-
|
|
605
|
+
interface VariantSelectorResult {
|
|
606
|
+
variantId?: string;
|
|
607
|
+
onOptionSelect: (key: string, value: string) => void;
|
|
608
|
+
getOptions: (key: string) => VariantSelectorOption[];
|
|
562
609
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
610
|
+
declare const useVariantSelector: <T extends {
|
|
611
|
+
id: string;
|
|
612
|
+
specs: Record<string, string>;
|
|
613
|
+
}>(props: VariantSelectorProps<T>) => VariantSelectorResult;
|
|
614
|
+
interface Category {
|
|
615
|
+
name: string;
|
|
566
616
|
}
|
|
567
|
-
interface
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
country?: string;
|
|
573
|
-
phone?: string;
|
|
574
|
-
email?: string;
|
|
617
|
+
interface Product {
|
|
618
|
+
name: string;
|
|
619
|
+
image: string;
|
|
620
|
+
item_code: string;
|
|
621
|
+
description: string;
|
|
575
622
|
}
|
|
576
|
-
interface
|
|
577
|
-
|
|
578
|
-
|
|
623
|
+
interface ProductVariant extends ItemVariant {
|
|
624
|
+
name: string;
|
|
625
|
+
currency: string;
|
|
626
|
+
rate: number;
|
|
627
|
+
qty: number;
|
|
628
|
+
images: string[];
|
|
629
|
+
specs: Record<string, string>;
|
|
579
630
|
}
|
|
580
|
-
interface
|
|
581
|
-
|
|
582
|
-
|
|
631
|
+
interface ShopContext {
|
|
632
|
+
categories: Category[];
|
|
633
|
+
grades: string[];
|
|
634
|
+
selected_category?: Category;
|
|
635
|
+
selected_grade?: string;
|
|
636
|
+
products: Product[];
|
|
583
637
|
}
|
|
584
|
-
interface
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
638
|
+
interface ProductContext {
|
|
639
|
+
product: Product;
|
|
640
|
+
specs: Record<string, string[]>;
|
|
641
|
+
variants: ProductVariant[];
|
|
642
|
+
models: Record<string, Model>;
|
|
643
|
+
colors: Record<string, Colour>;
|
|
588
644
|
}
|
|
589
645
|
import { camelize, decamelize, camelizeKeys, decamelizeKeys } from "humps";
|
|
590
646
|
declare function equalsIgnoreCase(str1: string, str2: string): boolean;
|
|
591
|
-
export { useSearch, useFrappeUpdateDoc, useFrappePutCall, useFrappePrefetchDoc, useFrappePostCall, useFrappeGetDocList, useFrappeGetDocCount, useFrappeGetDoc, useFrappeGetCall, useFrappeFileUpload, useFrappeEventListener, useFrappeDocumentEventListener, useFrappeDocTypeEventListener, useFrappeDeleteDoc, useFrappeDeleteCall, useFrappeCreateDoc, useFrappeAuth, equalsIgnoreCase, decamelizeKeys, decamelize, camelizeKeys, camelize, ViewerEventData, UseFrappeFileUploadReturnType, TopbarItem, Topbar, TokenParams, SearchResult, Page, NavbarSubItemGroup, NavbarSubItem, NavbarItem, Model, ItemVariant, Item, Hero, Header, Globals, FrappeProviderProps, FrappeProvider, FrappeMutationResult, FrappeFileUploadResponse, FrappeError, FrappeContext, FrappeConfig, FooterItemGroup, FooterItem, Footer, DocumentUpdateEventData, DocTypeListUpdateEventData, Colour, Brand, Block };
|
|
647
|
+
export { useVariantSelector, useSearch, useFrappeUpdateDoc, useFrappePutCall, useFrappePrefetchDoc, useFrappePostCall, useFrappeGetDocList, useFrappeGetDocCount, useFrappeGetDoc, useFrappeGetCall, useFrappeFileUpload, useFrappeEventListener, useFrappeDocumentEventListener, useFrappeDocTypeEventListener, useFrappeDeleteDoc, useFrappeDeleteCall, useFrappeCreateDoc, useFrappeAuth, equalsIgnoreCase, decamelizeKeys, decamelize, camelizeKeys, camelize, ViewerEventData, VariantSelectorResult, VariantSelectorProps, VariantSelectorOption, UseFrappeFileUploadReturnType, TopbarItem, Topbar, TokenParams, ShopContext, SearchResult, ProductVariant, ProductContext, Product, Page, NavbarSubItemGroup, NavbarSubItem, NavbarItem, Model, ItemVariant, Item, Hero, Header, Globals, FrappeProviderProps, FrappeProvider, FrappeMutationResult, FrappeFileUploadResponse, FrappeError, FrappeContext, FrappeConfig, FooterItemGroup, FooterItem, Footer, DocumentUpdateEventData, DocTypeListUpdateEventData, Colour, Category, Brand, Block };
|
package/dist/rn/index.js
CHANGED
|
@@ -46,7 +46,7 @@ class SocketIO {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
// src/frappe/provider.tsx
|
|
49
|
-
import {
|
|
49
|
+
import { jsx } from "react/jsx-runtime";
|
|
50
50
|
|
|
51
51
|
var FrappeContext = createContext(null);
|
|
52
52
|
var FrappeProvider = ({
|
|
@@ -71,10 +71,10 @@ var FrappeProvider = ({
|
|
|
71
71
|
socket: enableSocket ? new SocketIO(url, siteName, socketPort, tokenParams).socket : undefined
|
|
72
72
|
};
|
|
73
73
|
}, [url, tokenParams, enableSocket, socketPort, siteName, customHeaders]);
|
|
74
|
-
return /* @__PURE__ */
|
|
74
|
+
return /* @__PURE__ */ jsx(FrappeContext.Provider, {
|
|
75
75
|
value: frappeConfig,
|
|
76
76
|
children
|
|
77
|
-
}
|
|
77
|
+
});
|
|
78
78
|
};
|
|
79
79
|
// src/frappe/hooks/auth.ts
|
|
80
80
|
import { useCallback, useContext, useState, useEffect } from "react";
|
|
@@ -465,12 +465,118 @@ var useFrappeUpdateDoc = () => {
|
|
|
465
465
|
reset
|
|
466
466
|
};
|
|
467
467
|
};
|
|
468
|
+
// src/hooks/use-variant-selector/hook.ts
|
|
469
|
+
import { useCallback as useCallback4, useMemo as useMemo2, useState as useState5 } from "react";
|
|
470
|
+
|
|
471
|
+
// src/hooks/use-variant-selector/utils.ts
|
|
472
|
+
function findVariant(variants, specs, caseInsensitive) {
|
|
473
|
+
return variants.find((variant) => {
|
|
474
|
+
return Object.entries(specs).every(([key, value]) => {
|
|
475
|
+
const vv = variant.specs[key];
|
|
476
|
+
if (!vv)
|
|
477
|
+
return false;
|
|
478
|
+
if (caseInsensitive) {
|
|
479
|
+
return vv.toLowerCase() === value.toLowerCase();
|
|
480
|
+
}
|
|
481
|
+
return vv === value;
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
function findVariants(variants, specs, caseInsensitive) {
|
|
486
|
+
return variants.filter((variant) => {
|
|
487
|
+
return Object.entries(specs).every(([key, value]) => {
|
|
488
|
+
const vv = variant.specs[key];
|
|
489
|
+
if (!vv)
|
|
490
|
+
return false;
|
|
491
|
+
if (caseInsensitive) {
|
|
492
|
+
return vv.toLowerCase() === value.toLowerCase();
|
|
493
|
+
}
|
|
494
|
+
return vv === value;
|
|
495
|
+
});
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// src/hooks/use-variant-selector/hook.ts
|
|
500
|
+
var useVariantSelector = (props) => {
|
|
501
|
+
const { variants, attributes, defaultId } = props;
|
|
502
|
+
const [selectedSpecs, setSelectedSpecs] = useState5(() => {
|
|
503
|
+
if (defaultId) {
|
|
504
|
+
const variant = variants.find((v) => v.id === defaultId);
|
|
505
|
+
return variant?.specs || {};
|
|
506
|
+
}
|
|
507
|
+
return {};
|
|
508
|
+
});
|
|
509
|
+
const variantId = useMemo2(() => {
|
|
510
|
+
const complete = attributes.every((attr) => selectedSpecs[attr.key]);
|
|
511
|
+
if (!complete)
|
|
512
|
+
return;
|
|
513
|
+
const variant = findVariant(variants, selectedSpecs);
|
|
514
|
+
return variant?.id;
|
|
515
|
+
}, [variants, selectedSpecs, attributes]);
|
|
516
|
+
const options = useMemo2(() => {
|
|
517
|
+
const result = {};
|
|
518
|
+
attributes.forEach((attr, attrIndex) => {
|
|
519
|
+
const constraints = {};
|
|
520
|
+
for (let i = 0;i < attrIndex; i++) {
|
|
521
|
+
const key = attributes[i]?.key;
|
|
522
|
+
if (key && selectedSpecs[key])
|
|
523
|
+
constraints[key] = selectedSpecs[key];
|
|
524
|
+
}
|
|
525
|
+
const matchingVariants = findVariants(variants, constraints);
|
|
526
|
+
const availableValues = new Set(matchingVariants.map((v) => v.specs[attr.key]));
|
|
527
|
+
result[attr.key] = attr.values.map((value) => {
|
|
528
|
+
const isSelected = selectedSpecs[attr.key] === value;
|
|
529
|
+
const isAvailable = availableValues.has(value);
|
|
530
|
+
return {
|
|
531
|
+
key: attr.key,
|
|
532
|
+
value,
|
|
533
|
+
state: isSelected ? "selected" : isAvailable ? "available" : "unavailable"
|
|
534
|
+
};
|
|
535
|
+
});
|
|
536
|
+
});
|
|
537
|
+
return result;
|
|
538
|
+
}, [variants, attributes, selectedSpecs]);
|
|
539
|
+
const onOptionSelect = useCallback4((key, value) => {
|
|
540
|
+
setSelectedSpecs((prev) => {
|
|
541
|
+
const newSpecs = { ...prev, [key]: value };
|
|
542
|
+
const attrIndex = attributes.findIndex((a) => a.key === key);
|
|
543
|
+
for (let i = attrIndex + 1;i < attributes.length; i++) {
|
|
544
|
+
const downstreamAttr = attributes[i];
|
|
545
|
+
if (!downstreamAttr)
|
|
546
|
+
continue;
|
|
547
|
+
const constraints = {};
|
|
548
|
+
for (let j = 0;j < i; j++) {
|
|
549
|
+
const k = attributes[j]?.key;
|
|
550
|
+
if (k && newSpecs[k])
|
|
551
|
+
constraints[k] = newSpecs[k];
|
|
552
|
+
}
|
|
553
|
+
const matching = findVariants(variants, constraints);
|
|
554
|
+
const availableValues = new Set(matching.map((v) => v.specs[downstreamAttr.key]));
|
|
555
|
+
if (!availableValues.has(newSpecs[downstreamAttr.key])) {
|
|
556
|
+
const firstAvailable = downstreamAttr.values.find((v) => availableValues.has(v));
|
|
557
|
+
if (firstAvailable) {
|
|
558
|
+
newSpecs[downstreamAttr.key] = firstAvailable;
|
|
559
|
+
} else {
|
|
560
|
+
delete newSpecs[downstreamAttr.key];
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
return newSpecs;
|
|
565
|
+
});
|
|
566
|
+
}, [attributes, variants]);
|
|
567
|
+
return {
|
|
568
|
+
variantId,
|
|
569
|
+
onOptionSelect,
|
|
570
|
+
getOptions: (key) => options[key] || []
|
|
571
|
+
};
|
|
572
|
+
};
|
|
468
573
|
// src/utils/char.ts
|
|
469
574
|
import { camelize, decamelize, camelizeKeys, decamelizeKeys } from "humps";
|
|
470
575
|
function equalsIgnoreCase(str1, str2) {
|
|
471
576
|
return str1.localeCompare(str2, undefined, { sensitivity: "accent" }) === 0;
|
|
472
577
|
}
|
|
473
578
|
export {
|
|
579
|
+
useVariantSelector,
|
|
474
580
|
useSearch,
|
|
475
581
|
useFrappeUpdateDoc,
|
|
476
582
|
useFrappePutCall,
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lasterp/shared",
|
|
3
|
-
"version": "1.0.0-
|
|
3
|
+
"version": "1.0.0-beta.0",
|
|
4
4
|
"description": "Shared repo for webapp and native app",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist"
|
|
8
8
|
],
|
|
9
9
|
"scripts": {
|
|
10
|
-
"build": "bunup",
|
|
10
|
+
"build": "NODE_ENV=production bunup",
|
|
11
11
|
"dev": "bunup --watch",
|
|
12
12
|
"type-check": "tsc --noEmit"
|
|
13
13
|
},
|
package/dist/index.d.ts
DELETED