ads-nuxt 0.1.1 → 0.1.2
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/LICENSE +21 -21
- package/README.md +567 -546
- package/app/app.config.ts +25 -25
- package/app/assets/ads/checkbox-check.svg +5 -5
- package/app/assets/ads/checkbox-minus.svg +5 -5
- package/app/assets/brand/farmarcas.svg +6 -6
- package/app/assets/brand/radar.svg +9 -9
- package/app/assets/css/component-tokens.css +403 -403
- package/app/assets/css/main.css +617 -617
- package/app/components/AdsBadge.vue +48 -48
- package/app/components/AdsBroadcast.vue +45 -45
- package/app/components/AdsButton.vue +569 -569
- package/app/components/AdsButtonGroup.vue +39 -39
- package/app/components/AdsButtonMenu.vue +48 -48
- package/app/components/AdsCard.vue +117 -117
- package/app/components/AdsCharttip.vue +78 -78
- package/app/components/AdsCheckbox.vue +77 -77
- package/app/components/AdsDatePicker.vue +473 -473
- package/app/components/AdsDropdownMenu.vue +19 -19
- package/app/components/AdsEmptyState.vue +58 -58
- package/app/components/AdsFarmarcasPill.vue +74 -74
- package/app/components/AdsFeatureCard.vue +217 -217
- package/app/components/AdsFileCard.vue +101 -101
- package/app/components/AdsFilterDropdown.vue +174 -174
- package/app/components/AdsFilterOption.vue +72 -72
- package/app/components/AdsFilterSelect.vue +202 -202
- package/app/components/AdsFooter.vue +25 -25
- package/app/components/AdsInput.vue +143 -143
- package/app/components/AdsListDropdown.vue +44 -44
- package/app/components/AdsLoading.vue +109 -109
- package/app/components/AdsMenuBar.vue +103 -103
- package/app/components/AdsMetricCard.vue +119 -119
- package/app/components/AdsMiniPill.vue +40 -40
- package/app/components/AdsModal.vue +157 -157
- package/app/components/AdsMonthPicker.vue +80 -80
- package/app/components/AdsNavbarApp.vue +67 -67
- package/app/components/AdsNavbarDesk.vue +62 -62
- package/app/components/AdsNotabilityPill.vue +27 -27
- package/app/components/AdsNumberInput.vue +166 -166
- package/app/components/AdsPagination.vue +91 -91
- package/app/components/AdsProductTag.vue +61 -61
- package/app/components/AdsRadio.vue +70 -70
- package/app/components/AdsSearchInput.vue +113 -113
- package/app/components/AdsSegmentedTabs.vue +28 -28
- package/app/components/AdsSideMenu.vue +101 -101
- package/app/components/AdsSmalltip.vue +44 -44
- package/app/components/AdsSteptip.vue +101 -101
- package/app/components/AdsSwitch.vue +59 -59
- package/app/components/AdsTable.vue +100 -100
- package/app/components/AdsTableToolbar.vue +44 -44
- package/app/components/AdsTabs.vue +51 -51
- package/app/components/AdsTextarea.vue +109 -109
- package/app/components/AdsToast.vue +181 -181
- package/app/components/AdsTooltip.vue +66 -66
- package/app/components/InvertedTooltip.vue +40 -40
- package/app/components/OverlayLoading.vue +173 -173
- package/app/components/ProgressBarLoading.vue +256 -256
- package/app/composables/useOverlayLoading.ts +66 -66
- package/app/locale/pt-br.ts +6 -6
- package/app/plugins/ads-toast.client.ts +24 -24
- package/app/theme/ads-theme.ts +370 -370
- package/app/theme/component-tokens.json +402 -402
- package/app/theme/component-tokens.ts +815 -815
- package/app/types/overlay-loading.types.ts +26 -26
- package/app/utils/ads-filter-select.ts +172 -172
- package/app/utils/ads-table.ts +204 -204
- package/app/utils/calendar-date.ts +128 -128
- package/app/utils/category-role.ts +45 -45
- package/app/utils/money.ts +77 -77
- package/app/utils/notability.ts +8 -8
- package/app/utils/parser.ts +134 -134
- package/app/utils/percentage.ts +54 -54
- package/nuxt.config.ts +31 -32
- package/package.json +48 -46
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
export type OverlayVariant =
|
|
2
|
-
| "loading"
|
|
3
|
-
| "success"
|
|
4
|
-
| "error"
|
|
5
|
-
| "search"
|
|
6
|
-
| "info";
|
|
7
|
-
|
|
8
|
-
export type OverlayClosableVariant = "success" | "error";
|
|
9
|
-
|
|
10
|
-
export interface OverlayLoadingOptions {
|
|
11
|
-
title?: string;
|
|
12
|
-
description?: string;
|
|
13
|
-
hint?: string;
|
|
14
|
-
showProgress?: boolean;
|
|
15
|
-
progress?: number;
|
|
16
|
-
variant?: OverlayVariant;
|
|
17
|
-
iconSrc?: string;
|
|
18
|
-
actionLabel?: string;
|
|
19
|
-
onAction?: () => void;
|
|
20
|
-
onUserClose?: () => void;
|
|
21
|
-
closableVariants?: OverlayClosableVariant[];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface OverlayLoadingProps extends OverlayLoadingOptions {
|
|
25
|
-
isVisible: boolean;
|
|
26
|
-
}
|
|
1
|
+
export type OverlayVariant =
|
|
2
|
+
| "loading"
|
|
3
|
+
| "success"
|
|
4
|
+
| "error"
|
|
5
|
+
| "search"
|
|
6
|
+
| "info";
|
|
7
|
+
|
|
8
|
+
export type OverlayClosableVariant = "success" | "error";
|
|
9
|
+
|
|
10
|
+
export interface OverlayLoadingOptions {
|
|
11
|
+
title?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
hint?: string;
|
|
14
|
+
showProgress?: boolean;
|
|
15
|
+
progress?: number;
|
|
16
|
+
variant?: OverlayVariant;
|
|
17
|
+
iconSrc?: string;
|
|
18
|
+
actionLabel?: string;
|
|
19
|
+
onAction?: () => void;
|
|
20
|
+
onUserClose?: () => void;
|
|
21
|
+
closableVariants?: OverlayClosableVariant[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface OverlayLoadingProps extends OverlayLoadingOptions {
|
|
25
|
+
isVisible: boolean;
|
|
26
|
+
}
|
|
@@ -1,172 +1,172 @@
|
|
|
1
|
-
/** Reticências a partir deste tamanho. A tooltip só entra quando o rótulo passa daqui. */
|
|
2
|
-
export const ADS_FILTER_LABEL_LIMIT = 22;
|
|
3
|
-
|
|
4
|
-
export const ADS_FILTER_MONTHS = [
|
|
5
|
-
{ short: "Jan", full: "Janeiro" },
|
|
6
|
-
{ short: "Fev", full: "Fevereiro" },
|
|
7
|
-
{ short: "Mar", full: "Março" },
|
|
8
|
-
{ short: "Abr", full: "Abril" },
|
|
9
|
-
{ short: "Mai", full: "Maio" },
|
|
10
|
-
{ short: "Jun", full: "Junho" },
|
|
11
|
-
{ short: "Jul", full: "Julho" },
|
|
12
|
-
{ short: "Ago", full: "Agosto" },
|
|
13
|
-
{ short: "Set", full: "Setembro" },
|
|
14
|
-
{ short: "Out", full: "Outubro" },
|
|
15
|
-
{ short: "Nov", full: "Novembro" },
|
|
16
|
-
{ short: "Dez", full: "Dezembro" },
|
|
17
|
-
] as const;
|
|
18
|
-
|
|
19
|
-
export interface AdsFilterOption {
|
|
20
|
-
value: string;
|
|
21
|
-
label: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export const toAdsFilterOptions = (
|
|
25
|
-
items: readonly {
|
|
26
|
-
id?: string;
|
|
27
|
-
value?: string;
|
|
28
|
-
name?: string;
|
|
29
|
-
label?: string;
|
|
30
|
-
}[],
|
|
31
|
-
): AdsFilterOption[] =>
|
|
32
|
-
items.map((item) => ({
|
|
33
|
-
value: item.value ?? item.id ?? "",
|
|
34
|
-
label: item.label ?? item.name ?? "",
|
|
35
|
-
}));
|
|
36
|
-
|
|
37
|
-
export type AdsFilterType = "checkbox" | "radio" | "month";
|
|
38
|
-
export type AdsFilterCheckState = "all" | "none" | "partial";
|
|
39
|
-
|
|
40
|
-
const MONTH_VALUE = /^(\d{4})-(\d{2})$/;
|
|
41
|
-
|
|
42
|
-
export const truncateFilterLabel = (
|
|
43
|
-
label: string,
|
|
44
|
-
limit = ADS_FILTER_LABEL_LIMIT,
|
|
45
|
-
): string => {
|
|
46
|
-
if (label.length <= limit) return label;
|
|
47
|
-
return `${label.slice(0, limit)}...`;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export const filterLabelNeedsTooltip = (
|
|
51
|
-
label: string,
|
|
52
|
-
limit = ADS_FILTER_LABEL_LIMIT,
|
|
53
|
-
): boolean => label.length > limit;
|
|
54
|
-
|
|
55
|
-
export const normalizeFilterQuery = (query: string): string =>
|
|
56
|
-
query.trim().toLocaleLowerCase("pt-BR");
|
|
57
|
-
|
|
58
|
-
export const groupFilterOptions = (
|
|
59
|
-
options: readonly AdsFilterOption[],
|
|
60
|
-
query: string,
|
|
61
|
-
): { exact: AdsFilterOption[]; matches: AdsFilterOption[]; empty: boolean } => {
|
|
62
|
-
const normalized = normalizeFilterQuery(query);
|
|
63
|
-
if (!normalized) {
|
|
64
|
-
return { exact: [], matches: [...options], empty: false };
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const exact: AdsFilterOption[] = [];
|
|
68
|
-
const matches: AdsFilterOption[] = [];
|
|
69
|
-
for (const option of options) {
|
|
70
|
-
const label = option.label.toLocaleLowerCase("pt-BR");
|
|
71
|
-
if (label === normalized) exact.push(option);
|
|
72
|
-
else if (label.includes(normalized)) matches.push(option);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
exact,
|
|
77
|
-
matches,
|
|
78
|
-
empty: exact.length === 0 && matches.length === 0,
|
|
79
|
-
};
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export const selectionCheckState = (
|
|
83
|
-
selected: readonly string[],
|
|
84
|
-
options: readonly AdsFilterOption[],
|
|
85
|
-
): AdsFilterCheckState => {
|
|
86
|
-
if (options.length === 0) return "none";
|
|
87
|
-
|
|
88
|
-
const selectedSet = new Set(selected);
|
|
89
|
-
let count = 0;
|
|
90
|
-
for (const option of options) {
|
|
91
|
-
if (selectedSet.has(option.value)) count += 1;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (count === 0) return "none";
|
|
95
|
-
if (count === options.length) return "all";
|
|
96
|
-
return "partial";
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
export const toggleFilterValue = (
|
|
100
|
-
selected: readonly string[],
|
|
101
|
-
value: string,
|
|
102
|
-
): string[] =>
|
|
103
|
-
selected.includes(value)
|
|
104
|
-
? selected.filter((item) => item !== value)
|
|
105
|
-
: [...selected, value];
|
|
106
|
-
|
|
107
|
-
export const toggleSelectAll = (
|
|
108
|
-
selected: readonly string[],
|
|
109
|
-
options: readonly AdsFilterOption[],
|
|
110
|
-
): string[] => {
|
|
111
|
-
if (selectionCheckState(selected, options) === "all") return [];
|
|
112
|
-
return options.map((option) => option.value);
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
export const parseMonthValue = (
|
|
116
|
-
value: string,
|
|
117
|
-
): { year: number; monthIndex: number } | null => {
|
|
118
|
-
const match = MONTH_VALUE.exec(value);
|
|
119
|
-
if (!match) return null;
|
|
120
|
-
|
|
121
|
-
const year = Number(match[1]);
|
|
122
|
-
const month = Number(match[2]);
|
|
123
|
-
if (month < 1 || month > 12) return null;
|
|
124
|
-
return { year, monthIndex: month - 1 };
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
export const formatMonthValue = (year: number, monthIndex: number): string =>
|
|
128
|
-
`${year}-${String(monthIndex + 1).padStart(2, "0")}`;
|
|
129
|
-
|
|
130
|
-
export const monthTriggerLabel = (value: string, placeholder: string): string => {
|
|
131
|
-
const parsed = parseMonthValue(value);
|
|
132
|
-
if (!parsed) return placeholder;
|
|
133
|
-
return ADS_FILTER_MONTHS[parsed.monthIndex]?.full ?? placeholder;
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
const selectedCountLabel = (count: number): string =>
|
|
137
|
-
count === 1 ? "1 selecionado" : `${count} selecionados`;
|
|
138
|
-
|
|
139
|
-
export const filterTriggerLabel = (params: {
|
|
140
|
-
type: AdsFilterType;
|
|
141
|
-
value: string | readonly string[];
|
|
142
|
-
options: readonly AdsFilterOption[];
|
|
143
|
-
placeholder: string;
|
|
144
|
-
allSelectedLabel: string;
|
|
145
|
-
}): string => {
|
|
146
|
-
if (params.type === "month") {
|
|
147
|
-
const current = typeof params.value === "string" ? params.value : "";
|
|
148
|
-
return monthTriggerLabel(current, params.placeholder);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (params.type === "radio") {
|
|
152
|
-
const current = typeof params.value === "string" ? params.value : "";
|
|
153
|
-
if (!current) return params.placeholder;
|
|
154
|
-
return (
|
|
155
|
-
params.options.find((option) => option.value === current)?.label ??
|
|
156
|
-
params.placeholder
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const selected = Array.isArray(params.value) ? [...params.value] : [];
|
|
161
|
-
if (selectionCheckState(selected, params.options) === "all") {
|
|
162
|
-
return params.allSelectedLabel;
|
|
163
|
-
}
|
|
164
|
-
if (selected.length === 0) return params.placeholder;
|
|
165
|
-
if (selected.length === 1) {
|
|
166
|
-
return (
|
|
167
|
-
params.options.find((option) => option.value === selected[0])?.label ??
|
|
168
|
-
selectedCountLabel(1)
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
return selectedCountLabel(selected.length);
|
|
172
|
-
};
|
|
1
|
+
/** Reticências a partir deste tamanho. A tooltip só entra quando o rótulo passa daqui. */
|
|
2
|
+
export const ADS_FILTER_LABEL_LIMIT = 22;
|
|
3
|
+
|
|
4
|
+
export const ADS_FILTER_MONTHS = [
|
|
5
|
+
{ short: "Jan", full: "Janeiro" },
|
|
6
|
+
{ short: "Fev", full: "Fevereiro" },
|
|
7
|
+
{ short: "Mar", full: "Março" },
|
|
8
|
+
{ short: "Abr", full: "Abril" },
|
|
9
|
+
{ short: "Mai", full: "Maio" },
|
|
10
|
+
{ short: "Jun", full: "Junho" },
|
|
11
|
+
{ short: "Jul", full: "Julho" },
|
|
12
|
+
{ short: "Ago", full: "Agosto" },
|
|
13
|
+
{ short: "Set", full: "Setembro" },
|
|
14
|
+
{ short: "Out", full: "Outubro" },
|
|
15
|
+
{ short: "Nov", full: "Novembro" },
|
|
16
|
+
{ short: "Dez", full: "Dezembro" },
|
|
17
|
+
] as const;
|
|
18
|
+
|
|
19
|
+
export interface AdsFilterOption {
|
|
20
|
+
value: string;
|
|
21
|
+
label: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const toAdsFilterOptions = (
|
|
25
|
+
items: readonly {
|
|
26
|
+
id?: string;
|
|
27
|
+
value?: string;
|
|
28
|
+
name?: string;
|
|
29
|
+
label?: string;
|
|
30
|
+
}[],
|
|
31
|
+
): AdsFilterOption[] =>
|
|
32
|
+
items.map((item) => ({
|
|
33
|
+
value: item.value ?? item.id ?? "",
|
|
34
|
+
label: item.label ?? item.name ?? "",
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
export type AdsFilterType = "checkbox" | "radio" | "month";
|
|
38
|
+
export type AdsFilterCheckState = "all" | "none" | "partial";
|
|
39
|
+
|
|
40
|
+
const MONTH_VALUE = /^(\d{4})-(\d{2})$/;
|
|
41
|
+
|
|
42
|
+
export const truncateFilterLabel = (
|
|
43
|
+
label: string,
|
|
44
|
+
limit = ADS_FILTER_LABEL_LIMIT,
|
|
45
|
+
): string => {
|
|
46
|
+
if (label.length <= limit) return label;
|
|
47
|
+
return `${label.slice(0, limit)}...`;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const filterLabelNeedsTooltip = (
|
|
51
|
+
label: string,
|
|
52
|
+
limit = ADS_FILTER_LABEL_LIMIT,
|
|
53
|
+
): boolean => label.length > limit;
|
|
54
|
+
|
|
55
|
+
export const normalizeFilterQuery = (query: string): string =>
|
|
56
|
+
query.trim().toLocaleLowerCase("pt-BR");
|
|
57
|
+
|
|
58
|
+
export const groupFilterOptions = (
|
|
59
|
+
options: readonly AdsFilterOption[],
|
|
60
|
+
query: string,
|
|
61
|
+
): { exact: AdsFilterOption[]; matches: AdsFilterOption[]; empty: boolean } => {
|
|
62
|
+
const normalized = normalizeFilterQuery(query);
|
|
63
|
+
if (!normalized) {
|
|
64
|
+
return { exact: [], matches: [...options], empty: false };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const exact: AdsFilterOption[] = [];
|
|
68
|
+
const matches: AdsFilterOption[] = [];
|
|
69
|
+
for (const option of options) {
|
|
70
|
+
const label = option.label.toLocaleLowerCase("pt-BR");
|
|
71
|
+
if (label === normalized) exact.push(option);
|
|
72
|
+
else if (label.includes(normalized)) matches.push(option);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
exact,
|
|
77
|
+
matches,
|
|
78
|
+
empty: exact.length === 0 && matches.length === 0,
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const selectionCheckState = (
|
|
83
|
+
selected: readonly string[],
|
|
84
|
+
options: readonly AdsFilterOption[],
|
|
85
|
+
): AdsFilterCheckState => {
|
|
86
|
+
if (options.length === 0) return "none";
|
|
87
|
+
|
|
88
|
+
const selectedSet = new Set(selected);
|
|
89
|
+
let count = 0;
|
|
90
|
+
for (const option of options) {
|
|
91
|
+
if (selectedSet.has(option.value)) count += 1;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (count === 0) return "none";
|
|
95
|
+
if (count === options.length) return "all";
|
|
96
|
+
return "partial";
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const toggleFilterValue = (
|
|
100
|
+
selected: readonly string[],
|
|
101
|
+
value: string,
|
|
102
|
+
): string[] =>
|
|
103
|
+
selected.includes(value)
|
|
104
|
+
? selected.filter((item) => item !== value)
|
|
105
|
+
: [...selected, value];
|
|
106
|
+
|
|
107
|
+
export const toggleSelectAll = (
|
|
108
|
+
selected: readonly string[],
|
|
109
|
+
options: readonly AdsFilterOption[],
|
|
110
|
+
): string[] => {
|
|
111
|
+
if (selectionCheckState(selected, options) === "all") return [];
|
|
112
|
+
return options.map((option) => option.value);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const parseMonthValue = (
|
|
116
|
+
value: string,
|
|
117
|
+
): { year: number; monthIndex: number } | null => {
|
|
118
|
+
const match = MONTH_VALUE.exec(value);
|
|
119
|
+
if (!match) return null;
|
|
120
|
+
|
|
121
|
+
const year = Number(match[1]);
|
|
122
|
+
const month = Number(match[2]);
|
|
123
|
+
if (month < 1 || month > 12) return null;
|
|
124
|
+
return { year, monthIndex: month - 1 };
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export const formatMonthValue = (year: number, monthIndex: number): string =>
|
|
128
|
+
`${year}-${String(monthIndex + 1).padStart(2, "0")}`;
|
|
129
|
+
|
|
130
|
+
export const monthTriggerLabel = (value: string, placeholder: string): string => {
|
|
131
|
+
const parsed = parseMonthValue(value);
|
|
132
|
+
if (!parsed) return placeholder;
|
|
133
|
+
return ADS_FILTER_MONTHS[parsed.monthIndex]?.full ?? placeholder;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const selectedCountLabel = (count: number): string =>
|
|
137
|
+
count === 1 ? "1 selecionado" : `${count} selecionados`;
|
|
138
|
+
|
|
139
|
+
export const filterTriggerLabel = (params: {
|
|
140
|
+
type: AdsFilterType;
|
|
141
|
+
value: string | readonly string[];
|
|
142
|
+
options: readonly AdsFilterOption[];
|
|
143
|
+
placeholder: string;
|
|
144
|
+
allSelectedLabel: string;
|
|
145
|
+
}): string => {
|
|
146
|
+
if (params.type === "month") {
|
|
147
|
+
const current = typeof params.value === "string" ? params.value : "";
|
|
148
|
+
return monthTriggerLabel(current, params.placeholder);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (params.type === "radio") {
|
|
152
|
+
const current = typeof params.value === "string" ? params.value : "";
|
|
153
|
+
if (!current) return params.placeholder;
|
|
154
|
+
return (
|
|
155
|
+
params.options.find((option) => option.value === current)?.label ??
|
|
156
|
+
params.placeholder
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const selected = Array.isArray(params.value) ? [...params.value] : [];
|
|
161
|
+
if (selectionCheckState(selected, params.options) === "all") {
|
|
162
|
+
return params.allSelectedLabel;
|
|
163
|
+
}
|
|
164
|
+
if (selected.length === 0) return params.placeholder;
|
|
165
|
+
if (selected.length === 1) {
|
|
166
|
+
return (
|
|
167
|
+
params.options.find((option) => option.value === selected[0])?.label ??
|
|
168
|
+
selectedCountLabel(1)
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
return selectedCountLabel(selected.length);
|
|
172
|
+
};
|