@bagelink/vue 0.0.1296 → 0.0.1300
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/components/form/inputs/SignaturePad.vue.d.ts +3 -0
- package/dist/components/form/inputs/SignaturePad.vue.d.ts.map +1 -1
- package/dist/index.cjs +67 -12
- package/dist/index.mjs +67 -12
- package/dist/utils/timeAgo.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/form/inputs/SignaturePad.vue +52 -1
- package/src/utils/timeAgo.ts +41 -12
|
@@ -30,6 +30,7 @@ declare function undo(): void;
|
|
|
30
30
|
declare function addWaterMark(data: WaterMark): void;
|
|
31
31
|
type __VLS_PublicProps = {
|
|
32
32
|
modelValue?: any;
|
|
33
|
+
'file'?: File;
|
|
33
34
|
} & __VLS_Props;
|
|
34
35
|
declare const _default: import('vue').DefineComponent<__VLS_PublicProps, {
|
|
35
36
|
save: typeof save;
|
|
@@ -40,8 +41,10 @@ declare const _default: import('vue').DefineComponent<__VLS_PublicProps, {
|
|
|
40
41
|
fromDataURL: (url: string) => Promise<void> | undefined;
|
|
41
42
|
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
42
43
|
"update:modelValue": (value: any) => any;
|
|
44
|
+
"update:file": (value: File) => any;
|
|
43
45
|
}, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
44
46
|
"onUpdate:modelValue"?: ((value: any) => any) | undefined;
|
|
47
|
+
"onUpdate:file"?: ((value: File) => any) | undefined;
|
|
45
48
|
}>, {
|
|
46
49
|
clearable: boolean;
|
|
47
50
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SignaturePad.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/form/inputs/SignaturePad.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SignaturePad.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/form/inputs/SignaturePad.vue"],"names":[],"mappings":"AAuOA,OAAO,KAAK,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAKnE,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;CACb;AAED,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,WAAW,GAAG,YAAY,GAAG,eAAe,CAAA;AAEnF,KAAK,WAAW,GAAG;IAClB,SAAS,CAAC,EAAE,mBAAmB,CAAA;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB,CAAC;AAcF,iBAAS,KAAK,SAIb;AAED,iBAAS,IAAI,CAAC,MAAM,CAAC,EAAE,UAAU,sBAGhC;AA8BD,iBAAS,IAAI,SAMZ;AAiBD,iBAAS,YAAY,CAAC,IAAI,EAAE,SAAS,QA0BpC;AAmFD,KAAK,iBAAiB,GAAG;IACzB,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,MAAM,CAAC,EAAE,IAAI,CAAC;CACb,GAAG,WAAW,CAAC;;;;;;;uBA1IU,MAAM;;;;;;;;eApDnB,OAAO;;;;AA0RpB,wBAWG"}
|
package/dist/index.cjs
CHANGED
|
@@ -20586,7 +20586,7 @@ const _hoisted_2$g = {
|
|
|
20586
20586
|
placeholder: "required",
|
|
20587
20587
|
type: "text",
|
|
20588
20588
|
required: "",
|
|
20589
|
-
class: "pixel"
|
|
20589
|
+
class: "pixel opacity-0"
|
|
20590
20590
|
};
|
|
20591
20591
|
const _sfc_main$x = /* @__PURE__ */ vue.defineComponent({
|
|
20592
20592
|
__name: "SignaturePad",
|
|
@@ -20604,12 +20604,15 @@ const _sfc_main$x = /* @__PURE__ */ vue.defineComponent({
|
|
|
20604
20604
|
required: { type: Boolean }
|
|
20605
20605
|
}, {
|
|
20606
20606
|
"modelValue": {},
|
|
20607
|
-
"modelModifiers": {}
|
|
20607
|
+
"modelModifiers": {},
|
|
20608
|
+
"file": {},
|
|
20609
|
+
"fileModifiers": {}
|
|
20608
20610
|
}),
|
|
20609
|
-
emits: ["update:modelValue"],
|
|
20611
|
+
emits: ["update:modelValue", "update:file"],
|
|
20610
20612
|
setup(__props, { expose: __expose }) {
|
|
20611
20613
|
const props2 = __props;
|
|
20612
20614
|
const sigData = vue.useModel(__props, "modelValue");
|
|
20615
|
+
const fileData = vue.useModel(__props, "file");
|
|
20613
20616
|
const vCanvas = vue.ref();
|
|
20614
20617
|
let sig = vue.ref();
|
|
20615
20618
|
let _isEmpty = vue.ref(true);
|
|
@@ -20624,6 +20627,24 @@ const _sfc_main$x = /* @__PURE__ */ vue.defineComponent({
|
|
|
20624
20627
|
format2 = format2 || props2.format;
|
|
20625
20628
|
return format2 ? (_a = sig.value) == null ? void 0 : _a.toDataURL(format2) : (_b = sig.value) == null ? void 0 : _b.toDataURL();
|
|
20626
20629
|
}
|
|
20630
|
+
function saveFile() {
|
|
20631
|
+
const data2 = save2();
|
|
20632
|
+
if (!data2) return;
|
|
20633
|
+
if (props2.format === "image/svg+xml") {
|
|
20634
|
+
fileData.value = new File([data2], "signature.svg", { type: "image/svg+xml" });
|
|
20635
|
+
} else {
|
|
20636
|
+
const base64Data = data2.split(",")[1];
|
|
20637
|
+
const byteCharacters = atob(base64Data);
|
|
20638
|
+
const byteNumbers = new Array(byteCharacters.length);
|
|
20639
|
+
for (let i2 = 0; i2 < byteCharacters.length; i2++) {
|
|
20640
|
+
byteNumbers[i2] = byteCharacters.charCodeAt(i2);
|
|
20641
|
+
}
|
|
20642
|
+
const byteArray = new Uint8Array(byteNumbers);
|
|
20643
|
+
const blob = new Blob([byteArray], { type: props2.format || "image/png" });
|
|
20644
|
+
const extension = (props2.format || "image/png").split("/")[1];
|
|
20645
|
+
fileData.value = new File([blob], `signature.${extension}`, { type: props2.format || "image/png" });
|
|
20646
|
+
}
|
|
20647
|
+
}
|
|
20627
20648
|
const fromDataURL = (url) => {
|
|
20628
20649
|
var _a;
|
|
20629
20650
|
return (_a = sig.value) == null ? void 0 : _a.fromDataURL(url);
|
|
@@ -20685,7 +20706,26 @@ const _sfc_main$x = /* @__PURE__ */ vue.defineComponent({
|
|
|
20685
20706
|
_isEmpty.value = ((_a = sig.value) == null ? void 0 : _a.isEmpty()) ?? false;
|
|
20686
20707
|
const data2 = save2();
|
|
20687
20708
|
sigData.value = data2;
|
|
20709
|
+
saveFile();
|
|
20688
20710
|
}
|
|
20711
|
+
async function loadFile(file) {
|
|
20712
|
+
if (!file) return;
|
|
20713
|
+
const reader = new FileReader();
|
|
20714
|
+
return new Promise((resolve) => {
|
|
20715
|
+
reader.onload = (e) => {
|
|
20716
|
+
var _a;
|
|
20717
|
+
const dataUrl = (_a = e.target) == null ? void 0 : _a.result;
|
|
20718
|
+
fromDataURL(dataUrl);
|
|
20719
|
+
_isEmpty.value = false;
|
|
20720
|
+
sigData.value = dataUrl;
|
|
20721
|
+
resolve(true);
|
|
20722
|
+
};
|
|
20723
|
+
reader.readAsDataURL(file);
|
|
20724
|
+
});
|
|
20725
|
+
}
|
|
20726
|
+
vue.watch(fileData, (newFile) => {
|
|
20727
|
+
loadFile(newFile);
|
|
20728
|
+
});
|
|
20689
20729
|
function draw() {
|
|
20690
20730
|
const canvas = vCanvas.value;
|
|
20691
20731
|
sig.value = new SignaturePad(canvas, signatureOptions.value);
|
|
@@ -20708,6 +20748,9 @@ const _sfc_main$x = /* @__PURE__ */ vue.defineComponent({
|
|
|
20708
20748
|
else sig.value.on();
|
|
20709
20749
|
_isEmpty.value = sig.value.isEmpty();
|
|
20710
20750
|
sig.value.addEventListener("endStroke", onEndStroke);
|
|
20751
|
+
if (fileData.value) {
|
|
20752
|
+
loadFile(fileData.value);
|
|
20753
|
+
}
|
|
20711
20754
|
}
|
|
20712
20755
|
vue.onMounted(draw);
|
|
20713
20756
|
vue.onUnmounted(() => {
|
|
@@ -37167,16 +37210,16 @@ const translations = {
|
|
|
37167
37210
|
second: "seconde",
|
|
37168
37211
|
ago: "il y a",
|
|
37169
37212
|
in: "dans",
|
|
37170
|
-
justNow: "À l
|
|
37213
|
+
justNow: "À l'instant"
|
|
37171
37214
|
},
|
|
37172
37215
|
he: {
|
|
37173
|
-
year: "שנה",
|
|
37174
|
-
month: "חודש",
|
|
37175
|
-
week: "שבוע",
|
|
37176
|
-
day: "יום",
|
|
37177
|
-
hour: "שעה",
|
|
37178
|
-
minute: "דקה",
|
|
37179
|
-
second: "שנייה",
|
|
37216
|
+
year: { singular: "שנה", plural: "שנים" },
|
|
37217
|
+
month: { singular: "חודש", plural: "חודשים" },
|
|
37218
|
+
week: { singular: "שבוע", plural: "שבועות" },
|
|
37219
|
+
day: { singular: "יום", plural: "ימים" },
|
|
37220
|
+
hour: { singular: "שעה", plural: "שעות" },
|
|
37221
|
+
minute: { singular: "דקה", plural: "דקות" },
|
|
37222
|
+
second: { singular: "שנייה", plural: "שניות" },
|
|
37180
37223
|
ago: "לפני",
|
|
37181
37224
|
in: "בעוד",
|
|
37182
37225
|
justNow: "זה עתה"
|
|
@@ -37203,7 +37246,19 @@ function timeAgo(date2, lang = "en") {
|
|
|
37203
37246
|
const count2 = Math.floor(Math.abs(seconds) / interval.seconds);
|
|
37204
37247
|
if (count2 >= 1) {
|
|
37205
37248
|
const suffix = seconds < 0 ? ` ${selectedLang.ago}` : "";
|
|
37206
|
-
const prefix = "";
|
|
37249
|
+
const prefix = seconds > 0 && selectedLang.in !== "in" ? `${selectedLang.in} ` : "";
|
|
37250
|
+
if (lang === "he") {
|
|
37251
|
+
const timeUnit = selectedLang[interval.label];
|
|
37252
|
+
const form = count2 === 1 ? timeUnit.singular : timeUnit.plural;
|
|
37253
|
+
const hebrewPrefix = seconds < 0 ? `${selectedLang.ago} ` : seconds > 0 ? `${selectedLang.in} ` : "";
|
|
37254
|
+
if (interval.label === "day" && seconds > 0) {
|
|
37255
|
+
const hours = Math.floor(Math.abs(seconds) % 86400 / 3600);
|
|
37256
|
+
const hourUnit = selectedLang.hour;
|
|
37257
|
+
const hourForm = hours === 1 ? hourUnit.singular : hourUnit.plural;
|
|
37258
|
+
return `${hebrewPrefix}${count2} ${form}${hours > 0 ? ` ${hours} ${hourForm}` : ""}`;
|
|
37259
|
+
}
|
|
37260
|
+
return `${hebrewPrefix}${count2} ${form}`;
|
|
37261
|
+
}
|
|
37207
37262
|
if (interval.label === "day" && seconds > 0) {
|
|
37208
37263
|
const hours = Math.floor(Math.abs(seconds) % 86400 / 3600);
|
|
37209
37264
|
const hourLabel = hours > 1 ? `${selectedLang.hour}s` : selectedLang.hour;
|
package/dist/index.mjs
CHANGED
|
@@ -20584,7 +20584,7 @@ const _hoisted_2$g = {
|
|
|
20584
20584
|
placeholder: "required",
|
|
20585
20585
|
type: "text",
|
|
20586
20586
|
required: "",
|
|
20587
|
-
class: "pixel"
|
|
20587
|
+
class: "pixel opacity-0"
|
|
20588
20588
|
};
|
|
20589
20589
|
const _sfc_main$x = /* @__PURE__ */ defineComponent({
|
|
20590
20590
|
__name: "SignaturePad",
|
|
@@ -20602,12 +20602,15 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
|
|
|
20602
20602
|
required: { type: Boolean }
|
|
20603
20603
|
}, {
|
|
20604
20604
|
"modelValue": {},
|
|
20605
|
-
"modelModifiers": {}
|
|
20605
|
+
"modelModifiers": {},
|
|
20606
|
+
"file": {},
|
|
20607
|
+
"fileModifiers": {}
|
|
20606
20608
|
}),
|
|
20607
|
-
emits: ["update:modelValue"],
|
|
20609
|
+
emits: ["update:modelValue", "update:file"],
|
|
20608
20610
|
setup(__props, { expose: __expose }) {
|
|
20609
20611
|
const props2 = __props;
|
|
20610
20612
|
const sigData = useModel(__props, "modelValue");
|
|
20613
|
+
const fileData = useModel(__props, "file");
|
|
20611
20614
|
const vCanvas = ref();
|
|
20612
20615
|
let sig = ref();
|
|
20613
20616
|
let _isEmpty = ref(true);
|
|
@@ -20622,6 +20625,24 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
|
|
|
20622
20625
|
format2 = format2 || props2.format;
|
|
20623
20626
|
return format2 ? (_a = sig.value) == null ? void 0 : _a.toDataURL(format2) : (_b = sig.value) == null ? void 0 : _b.toDataURL();
|
|
20624
20627
|
}
|
|
20628
|
+
function saveFile() {
|
|
20629
|
+
const data2 = save2();
|
|
20630
|
+
if (!data2) return;
|
|
20631
|
+
if (props2.format === "image/svg+xml") {
|
|
20632
|
+
fileData.value = new File([data2], "signature.svg", { type: "image/svg+xml" });
|
|
20633
|
+
} else {
|
|
20634
|
+
const base64Data = data2.split(",")[1];
|
|
20635
|
+
const byteCharacters = atob(base64Data);
|
|
20636
|
+
const byteNumbers = new Array(byteCharacters.length);
|
|
20637
|
+
for (let i2 = 0; i2 < byteCharacters.length; i2++) {
|
|
20638
|
+
byteNumbers[i2] = byteCharacters.charCodeAt(i2);
|
|
20639
|
+
}
|
|
20640
|
+
const byteArray = new Uint8Array(byteNumbers);
|
|
20641
|
+
const blob = new Blob([byteArray], { type: props2.format || "image/png" });
|
|
20642
|
+
const extension = (props2.format || "image/png").split("/")[1];
|
|
20643
|
+
fileData.value = new File([blob], `signature.${extension}`, { type: props2.format || "image/png" });
|
|
20644
|
+
}
|
|
20645
|
+
}
|
|
20625
20646
|
const fromDataURL = (url) => {
|
|
20626
20647
|
var _a;
|
|
20627
20648
|
return (_a = sig.value) == null ? void 0 : _a.fromDataURL(url);
|
|
@@ -20683,7 +20704,26 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
|
|
|
20683
20704
|
_isEmpty.value = ((_a = sig.value) == null ? void 0 : _a.isEmpty()) ?? false;
|
|
20684
20705
|
const data2 = save2();
|
|
20685
20706
|
sigData.value = data2;
|
|
20707
|
+
saveFile();
|
|
20686
20708
|
}
|
|
20709
|
+
async function loadFile(file) {
|
|
20710
|
+
if (!file) return;
|
|
20711
|
+
const reader = new FileReader();
|
|
20712
|
+
return new Promise((resolve) => {
|
|
20713
|
+
reader.onload = (e) => {
|
|
20714
|
+
var _a;
|
|
20715
|
+
const dataUrl = (_a = e.target) == null ? void 0 : _a.result;
|
|
20716
|
+
fromDataURL(dataUrl);
|
|
20717
|
+
_isEmpty.value = false;
|
|
20718
|
+
sigData.value = dataUrl;
|
|
20719
|
+
resolve(true);
|
|
20720
|
+
};
|
|
20721
|
+
reader.readAsDataURL(file);
|
|
20722
|
+
});
|
|
20723
|
+
}
|
|
20724
|
+
watch(fileData, (newFile) => {
|
|
20725
|
+
loadFile(newFile);
|
|
20726
|
+
});
|
|
20687
20727
|
function draw() {
|
|
20688
20728
|
const canvas = vCanvas.value;
|
|
20689
20729
|
sig.value = new SignaturePad(canvas, signatureOptions.value);
|
|
@@ -20706,6 +20746,9 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
|
|
|
20706
20746
|
else sig.value.on();
|
|
20707
20747
|
_isEmpty.value = sig.value.isEmpty();
|
|
20708
20748
|
sig.value.addEventListener("endStroke", onEndStroke);
|
|
20749
|
+
if (fileData.value) {
|
|
20750
|
+
loadFile(fileData.value);
|
|
20751
|
+
}
|
|
20709
20752
|
}
|
|
20710
20753
|
onMounted(draw);
|
|
20711
20754
|
onUnmounted(() => {
|
|
@@ -37165,16 +37208,16 @@ const translations = {
|
|
|
37165
37208
|
second: "seconde",
|
|
37166
37209
|
ago: "il y a",
|
|
37167
37210
|
in: "dans",
|
|
37168
|
-
justNow: "À l
|
|
37211
|
+
justNow: "À l'instant"
|
|
37169
37212
|
},
|
|
37170
37213
|
he: {
|
|
37171
|
-
year: "שנה",
|
|
37172
|
-
month: "חודש",
|
|
37173
|
-
week: "שבוע",
|
|
37174
|
-
day: "יום",
|
|
37175
|
-
hour: "שעה",
|
|
37176
|
-
minute: "דקה",
|
|
37177
|
-
second: "שנייה",
|
|
37214
|
+
year: { singular: "שנה", plural: "שנים" },
|
|
37215
|
+
month: { singular: "חודש", plural: "חודשים" },
|
|
37216
|
+
week: { singular: "שבוע", plural: "שבועות" },
|
|
37217
|
+
day: { singular: "יום", plural: "ימים" },
|
|
37218
|
+
hour: { singular: "שעה", plural: "שעות" },
|
|
37219
|
+
minute: { singular: "דקה", plural: "דקות" },
|
|
37220
|
+
second: { singular: "שנייה", plural: "שניות" },
|
|
37178
37221
|
ago: "לפני",
|
|
37179
37222
|
in: "בעוד",
|
|
37180
37223
|
justNow: "זה עתה"
|
|
@@ -37201,7 +37244,19 @@ function timeAgo(date2, lang = "en") {
|
|
|
37201
37244
|
const count2 = Math.floor(Math.abs(seconds) / interval.seconds);
|
|
37202
37245
|
if (count2 >= 1) {
|
|
37203
37246
|
const suffix = seconds < 0 ? ` ${selectedLang.ago}` : "";
|
|
37204
|
-
const prefix = "";
|
|
37247
|
+
const prefix = seconds > 0 && selectedLang.in !== "in" ? `${selectedLang.in} ` : "";
|
|
37248
|
+
if (lang === "he") {
|
|
37249
|
+
const timeUnit = selectedLang[interval.label];
|
|
37250
|
+
const form = count2 === 1 ? timeUnit.singular : timeUnit.plural;
|
|
37251
|
+
const hebrewPrefix = seconds < 0 ? `${selectedLang.ago} ` : seconds > 0 ? `${selectedLang.in} ` : "";
|
|
37252
|
+
if (interval.label === "day" && seconds > 0) {
|
|
37253
|
+
const hours = Math.floor(Math.abs(seconds) % 86400 / 3600);
|
|
37254
|
+
const hourUnit = selectedLang.hour;
|
|
37255
|
+
const hourForm = hours === 1 ? hourUnit.singular : hourUnit.plural;
|
|
37256
|
+
return `${hebrewPrefix}${count2} ${form}${hours > 0 ? ` ${hours} ${hourForm}` : ""}`;
|
|
37257
|
+
}
|
|
37258
|
+
return `${hebrewPrefix}${count2} ${form}`;
|
|
37259
|
+
}
|
|
37205
37260
|
if (interval.label === "day" && seconds > 0) {
|
|
37206
37261
|
const hours = Math.floor(Math.abs(seconds) % 86400 / 3600);
|
|
37207
37262
|
const hourLabel = hours > 1 ? `${selectedLang.hour}s` : selectedLang.hour;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeAgo.d.ts","sourceRoot":"","sources":["../../src/utils/timeAgo.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"timeAgo.d.ts","sourceRoot":"","sources":["../../src/utils/timeAgo.ts"],"names":[],"mappings":"AAWA,KAAK,sBAAsB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAqDvD,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,GAAE,sBAA6B,UAsD/E"}
|
package/package.json
CHANGED
|
@@ -35,6 +35,7 @@ const props = withDefaults(defineProps<{
|
|
|
35
35
|
})
|
|
36
36
|
|
|
37
37
|
const sigData = defineModel()
|
|
38
|
+
const fileData = defineModel<File>('file')
|
|
38
39
|
|
|
39
40
|
const vCanvas = $ref<HTMLCanvasElement>()
|
|
40
41
|
|
|
@@ -53,6 +54,31 @@ function save(format?: FormatType) {
|
|
|
53
54
|
return format ? sig?.toDataURL(format) : sig?.toDataURL()
|
|
54
55
|
}
|
|
55
56
|
|
|
57
|
+
function saveFile() {
|
|
58
|
+
const data = save()
|
|
59
|
+
if (!data) return
|
|
60
|
+
|
|
61
|
+
if (props.format === 'image/svg+xml') {
|
|
62
|
+
// For SVG, create file directly from the SVG string
|
|
63
|
+
fileData.value = new File([data], 'signature.svg', { type: 'image/svg+xml' })
|
|
64
|
+
} else {
|
|
65
|
+
// For PNG/JPG, convert base64 to blob first
|
|
66
|
+
const base64Data = data.split(',')[1]
|
|
67
|
+
const byteCharacters = atob(base64Data)
|
|
68
|
+
const byteNumbers = new Array(byteCharacters.length)
|
|
69
|
+
|
|
70
|
+
for (let i = 0; i < byteCharacters.length; i++) {
|
|
71
|
+
byteNumbers[i] = byteCharacters.charCodeAt(i)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const byteArray = new Uint8Array(byteNumbers)
|
|
75
|
+
const blob = new Blob([byteArray], { type: props.format || 'image/png' })
|
|
76
|
+
|
|
77
|
+
const extension = (props.format || 'image/png').split('/')[1]
|
|
78
|
+
fileData.value = new File([blob], `signature.${extension}`, { type: props.format || 'image/png' })
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
56
82
|
const fromDataURL = (url: string) => sig?.fromDataURL(url)
|
|
57
83
|
|
|
58
84
|
const isEmpty = () => sig?.isEmpty()
|
|
@@ -111,8 +137,28 @@ function onEndStroke() {
|
|
|
111
137
|
_isEmpty = sig?.isEmpty() ?? false
|
|
112
138
|
const data = save()
|
|
113
139
|
sigData.value = data
|
|
140
|
+
saveFile()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function loadFile(file: File | undefined) {
|
|
144
|
+
if (!file) return
|
|
145
|
+
const reader = new FileReader()
|
|
146
|
+
return new Promise((resolve) => {
|
|
147
|
+
reader.onload = (e) => {
|
|
148
|
+
const dataUrl = e.target?.result as string
|
|
149
|
+
fromDataURL(dataUrl)
|
|
150
|
+
_isEmpty = false
|
|
151
|
+
sigData.value = dataUrl
|
|
152
|
+
resolve(true)
|
|
153
|
+
}
|
|
154
|
+
reader.readAsDataURL(file)
|
|
155
|
+
})
|
|
114
156
|
}
|
|
115
157
|
|
|
158
|
+
watch(fileData, (newFile) => {
|
|
159
|
+
loadFile(newFile)
|
|
160
|
+
})
|
|
161
|
+
|
|
116
162
|
function draw() {
|
|
117
163
|
const canvas = vCanvas!
|
|
118
164
|
sig = new SignaturePad(canvas, signatureOptions)
|
|
@@ -133,6 +179,11 @@ function draw() {
|
|
|
133
179
|
else sig.on()
|
|
134
180
|
_isEmpty = sig.isEmpty()
|
|
135
181
|
sig.addEventListener('endStroke', onEndStroke)
|
|
182
|
+
|
|
183
|
+
// Load initial file if provided
|
|
184
|
+
if (fileData.value) {
|
|
185
|
+
loadFile(fileData.value)
|
|
186
|
+
}
|
|
136
187
|
}
|
|
137
188
|
|
|
138
189
|
onMounted(draw)
|
|
@@ -154,7 +205,7 @@ defineExpose({
|
|
|
154
205
|
<div class="bgl_input signature-pad relative" :class="{ 'bg-transparent': disabled }" @touchmove.prevent>
|
|
155
206
|
<Btn v-if="clearable && !disabled" flat thin icon="refresh" class="position-bottom-end" @click="clear" />
|
|
156
207
|
<canvas ref="vCanvas" class="canvas" :disabled />
|
|
157
|
-
<input v-if="required && _isEmpty" placeholder="required" type="text" required class="pixel">
|
|
208
|
+
<input v-if="required && _isEmpty" placeholder="required" type="text" required class="pixel opacity-0">
|
|
158
209
|
</div>
|
|
159
210
|
</template>
|
|
160
211
|
|
package/src/utils/timeAgo.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
interface TimeUnit {
|
|
2
|
+
singular: string
|
|
3
|
+
plural: string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
type TranslationValue = string | TimeUnit
|
|
7
|
+
|
|
2
8
|
interface LanguageTranslations {
|
|
3
|
-
[key: string]:
|
|
9
|
+
[key: string]: TranslationValue
|
|
4
10
|
}
|
|
11
|
+
|
|
12
|
+
type AvailableTimeLanguages = 'en' | 'es' | 'fr' | 'he'
|
|
13
|
+
|
|
5
14
|
const translations: Record<AvailableTimeLanguages, LanguageTranslations> = {
|
|
6
15
|
en: {
|
|
7
16
|
year: 'year',
|
|
@@ -37,21 +46,22 @@ const translations: Record<AvailableTimeLanguages, LanguageTranslations> = {
|
|
|
37
46
|
second: 'seconde',
|
|
38
47
|
ago: 'il y a',
|
|
39
48
|
in: 'dans',
|
|
40
|
-
justNow: 'À l
|
|
49
|
+
justNow: 'À l\'instant'
|
|
41
50
|
},
|
|
42
51
|
he: {
|
|
43
|
-
year: 'שנה',
|
|
44
|
-
month: 'חודש',
|
|
45
|
-
week: 'שבוע',
|
|
46
|
-
day: 'יום',
|
|
47
|
-
hour: 'שעה',
|
|
48
|
-
minute: 'דקה',
|
|
49
|
-
second: 'שנייה',
|
|
52
|
+
year: { singular: 'שנה', plural: 'שנים' },
|
|
53
|
+
month: { singular: 'חודש', plural: 'חודשים' },
|
|
54
|
+
week: { singular: 'שבוע', plural: 'שבועות' },
|
|
55
|
+
day: { singular: 'יום', plural: 'ימים' },
|
|
56
|
+
hour: { singular: 'שעה', plural: 'שעות' },
|
|
57
|
+
minute: { singular: 'דקה', plural: 'דקות' },
|
|
58
|
+
second: { singular: 'שנייה', plural: 'שניות' },
|
|
50
59
|
ago: 'לפני',
|
|
51
60
|
in: 'בעוד',
|
|
52
61
|
justNow: 'זה עתה'
|
|
53
62
|
}
|
|
54
63
|
}
|
|
64
|
+
|
|
55
65
|
export function timeAgo(date: string | Date, lang: AvailableTimeLanguages = 'en') {
|
|
56
66
|
if (!date) return ''
|
|
57
67
|
if (typeof date === 'string') date = new Date(date)
|
|
@@ -76,7 +86,26 @@ export function timeAgo(date: string | Date, lang: AvailableTimeLanguages = 'en'
|
|
|
76
86
|
const count = Math.floor(Math.abs(seconds) / interval.seconds)
|
|
77
87
|
if (count >= 1) {
|
|
78
88
|
const suffix = seconds < 0 ? ` ${selectedLang.ago}` : ''
|
|
79
|
-
const prefix = ''
|
|
89
|
+
const prefix = seconds > 0 && selectedLang.in !== 'in' ? `${selectedLang.in} ` : ''
|
|
90
|
+
|
|
91
|
+
// Handle Hebrew plural forms
|
|
92
|
+
if (lang === 'he') {
|
|
93
|
+
const timeUnit = selectedLang[interval.label] as TimeUnit
|
|
94
|
+
const form = count === 1 ? timeUnit.singular : timeUnit.plural
|
|
95
|
+
|
|
96
|
+
// For Hebrew, we place the prefix/suffix before the number
|
|
97
|
+
const hebrewPrefix = seconds < 0 ? `${selectedLang.ago} ` : (seconds > 0 ? `${selectedLang.in} ` : '')
|
|
98
|
+
|
|
99
|
+
if (interval.label === 'day' && seconds > 0) {
|
|
100
|
+
const hours = Math.floor((Math.abs(seconds) % 86400) / 3600)
|
|
101
|
+
const hourUnit = selectedLang.hour as TimeUnit
|
|
102
|
+
const hourForm = hours === 1 ? hourUnit.singular : hourUnit.plural
|
|
103
|
+
return `${hebrewPrefix}${count} ${form}${hours > 0 ? ` ${hours} ${hourForm}` : ''}`
|
|
104
|
+
}
|
|
105
|
+
return `${hebrewPrefix}${count} ${form}`
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Handle other languages
|
|
80
109
|
if (interval.label === 'day' && seconds > 0) {
|
|
81
110
|
const hours = Math.floor((Math.abs(seconds) % 86400) / 3600)
|
|
82
111
|
const hourLabel = hours > 1 ? `${selectedLang.hour}s` : selectedLang.hour
|
|
@@ -86,5 +115,5 @@ export function timeAgo(date: string | Date, lang: AvailableTimeLanguages = 'en'
|
|
|
86
115
|
}
|
|
87
116
|
}
|
|
88
117
|
|
|
89
|
-
return selectedLang.justNow
|
|
118
|
+
return selectedLang.justNow as string
|
|
90
119
|
}
|