@zag-js/clipboard 0.35.0 → 0.36.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/index.d.mts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +18 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +18 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
- package/src/clipboard.connect.ts +6 -0
- package/src/clipboard.dom.ts +3 -3
- package/src/clipboard.machine.ts +9 -2
- package/src/clipboard.types.ts +14 -0
- package/src/index.ts +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -8,7 +8,16 @@ declare const anatomy: _zag_js_anatomy.AnatomyInstance<"root" | "control" | "tri
|
|
|
8
8
|
interface CopyStatusDetails {
|
|
9
9
|
copied: boolean;
|
|
10
10
|
}
|
|
11
|
+
type ElementIds = Partial<{
|
|
12
|
+
root: string;
|
|
13
|
+
input: string;
|
|
14
|
+
label: string;
|
|
15
|
+
}>;
|
|
11
16
|
interface PublicContext extends CommonProperties {
|
|
17
|
+
/**
|
|
18
|
+
* The ids of the elements in the clipboard. Useful for composition.
|
|
19
|
+
*/
|
|
20
|
+
ids?: ElementIds;
|
|
12
21
|
/**
|
|
13
22
|
* The value to be copied to the clipboard
|
|
14
23
|
*/
|
|
@@ -48,6 +57,10 @@ interface MachineApi<T extends PropTypes = PropTypes> {
|
|
|
48
57
|
* Set the value to be copied to the clipboard
|
|
49
58
|
*/
|
|
50
59
|
setValue(value: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Copy the value to the clipboard
|
|
62
|
+
*/
|
|
63
|
+
copy(): void;
|
|
51
64
|
rootProps: T["element"];
|
|
52
65
|
labelProps: T["label"];
|
|
53
66
|
controlProps: T["element"];
|
|
@@ -60,4 +73,4 @@ declare function connect<T extends PropTypes>(state: State, send: Send, normaliz
|
|
|
60
73
|
|
|
61
74
|
declare function machine(userContext: UserDefinedContext): _zag_js_core.Machine<MachineContext, MachineState, _zag_js_core.StateMachine.AnyEventObject>;
|
|
62
75
|
|
|
63
|
-
export { type UserDefinedContext as Context, anatomy, connect, machine };
|
|
76
|
+
export { type UserDefinedContext as Context, type CopyStatusDetails, type ElementIds, type IndicatorProps, anatomy, connect, machine };
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,16 @@ declare const anatomy: _zag_js_anatomy.AnatomyInstance<"root" | "control" | "tri
|
|
|
8
8
|
interface CopyStatusDetails {
|
|
9
9
|
copied: boolean;
|
|
10
10
|
}
|
|
11
|
+
type ElementIds = Partial<{
|
|
12
|
+
root: string;
|
|
13
|
+
input: string;
|
|
14
|
+
label: string;
|
|
15
|
+
}>;
|
|
11
16
|
interface PublicContext extends CommonProperties {
|
|
17
|
+
/**
|
|
18
|
+
* The ids of the elements in the clipboard. Useful for composition.
|
|
19
|
+
*/
|
|
20
|
+
ids?: ElementIds;
|
|
12
21
|
/**
|
|
13
22
|
* The value to be copied to the clipboard
|
|
14
23
|
*/
|
|
@@ -48,6 +57,10 @@ interface MachineApi<T extends PropTypes = PropTypes> {
|
|
|
48
57
|
* Set the value to be copied to the clipboard
|
|
49
58
|
*/
|
|
50
59
|
setValue(value: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Copy the value to the clipboard
|
|
62
|
+
*/
|
|
63
|
+
copy(): void;
|
|
51
64
|
rootProps: T["element"];
|
|
52
65
|
labelProps: T["label"];
|
|
53
66
|
controlProps: T["element"];
|
|
@@ -60,4 +73,4 @@ declare function connect<T extends PropTypes>(state: State, send: Send, normaliz
|
|
|
60
73
|
|
|
61
74
|
declare function machine(userContext: UserDefinedContext): _zag_js_core.Machine<MachineContext, MachineState, _zag_js_core.StateMachine.AnyEventObject>;
|
|
62
75
|
|
|
63
|
-
export { type UserDefinedContext as Context, anatomy, connect, machine };
|
|
76
|
+
export { type UserDefinedContext as Context, type CopyStatusDetails, type ElementIds, type IndicatorProps, anatomy, connect, machine };
|
package/dist/index.js
CHANGED
|
@@ -38,9 +38,9 @@ var import_dom_query2 = require("@zag-js/dom-query");
|
|
|
38
38
|
var import_dom_query = require("@zag-js/dom-query");
|
|
39
39
|
var import_utils = require("@zag-js/utils");
|
|
40
40
|
var dom = (0, import_dom_query.createScope)({
|
|
41
|
-
getRootId: (ctx) => `clip-${ctx.id}`,
|
|
42
|
-
getInputId: (ctx) => `clip-input-${ctx.id}`,
|
|
43
|
-
getLabelId: (ctx) => `clip-label-${ctx.id}`,
|
|
41
|
+
getRootId: (ctx) => ctx.ids?.root ?? `clip-${ctx.id}`,
|
|
42
|
+
getInputId: (ctx) => ctx.ids?.input ?? `clip-input-${ctx.id}`,
|
|
43
|
+
getLabelId: (ctx) => ctx.ids?.label ?? `clip-label-${ctx.id}`,
|
|
44
44
|
getInputEl: (ctx) => dom.getById(ctx, dom.getInputId(ctx)),
|
|
45
45
|
writeToClipboard: (ctx) => copyText(dom.getDoc(ctx), ctx.value)
|
|
46
46
|
});
|
|
@@ -94,6 +94,9 @@ function connect(state, send, normalize) {
|
|
|
94
94
|
setValue(value) {
|
|
95
95
|
send({ type: "VALUE.SET", value });
|
|
96
96
|
},
|
|
97
|
+
copy() {
|
|
98
|
+
send({ type: "COPY" });
|
|
99
|
+
},
|
|
97
100
|
rootProps: normalize.element({
|
|
98
101
|
...parts.root.attrs,
|
|
99
102
|
"data-copied": (0, import_dom_query2.dataAttr)(isCopied),
|
|
@@ -118,6 +121,9 @@ function connect(state, send, normalize) {
|
|
|
118
121
|
id: dom.getInputId(state.context),
|
|
119
122
|
onFocus(event) {
|
|
120
123
|
event.currentTarget.select();
|
|
124
|
+
},
|
|
125
|
+
onCopy() {
|
|
126
|
+
send({ type: "INPUT.COPY" });
|
|
121
127
|
}
|
|
122
128
|
}),
|
|
123
129
|
triggerProps: normalize.button({
|
|
@@ -157,14 +163,18 @@ function machine(userContext) {
|
|
|
157
163
|
on: {
|
|
158
164
|
"VALUE.SET": {
|
|
159
165
|
actions: ["setValue"]
|
|
166
|
+
},
|
|
167
|
+
COPY: {
|
|
168
|
+
target: "copied",
|
|
169
|
+
actions: ["copyToClipboard", "invokeOnCopied"]
|
|
160
170
|
}
|
|
161
171
|
},
|
|
162
172
|
states: {
|
|
163
173
|
idle: {
|
|
164
174
|
on: {
|
|
165
|
-
COPY: {
|
|
175
|
+
"INPUT.COPY": {
|
|
166
176
|
target: "copied",
|
|
167
|
-
actions: ["
|
|
177
|
+
actions: ["invokeOnCopied"]
|
|
168
178
|
}
|
|
169
179
|
}
|
|
170
180
|
},
|
|
@@ -176,6 +186,9 @@ function machine(userContext) {
|
|
|
176
186
|
COPY: {
|
|
177
187
|
target: "copied",
|
|
178
188
|
actions: ["copyToClipboard", "invokeOnCopied"]
|
|
189
|
+
},
|
|
190
|
+
"INPUT.COPY": {
|
|
191
|
+
actions: ["invokeOnCopied"]
|
|
179
192
|
}
|
|
180
193
|
}
|
|
181
194
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/clipboard.anatomy.ts","../src/clipboard.connect.ts","../src/clipboard.dom.ts","../src/clipboard.machine.ts"],"sourcesContent":["export { anatomy } from \"./clipboard.anatomy\"\nexport { connect } from \"./clipboard.connect\"\nexport { machine } from \"./clipboard.machine\"\nexport type { UserDefinedContext as Context } from \"./clipboard.types\"\n","import { createAnatomy } from \"@zag-js/anatomy\"\n\nexport const anatomy = createAnatomy(\"clipboard\").parts(\"root\", \"control\", \"trigger\", \"indicator\", \"input\", \"label\")\n\nexport const parts = anatomy.build()\n","import { dataAttr } from \"@zag-js/dom-query\"\nimport type { NormalizeProps, PropTypes } from \"@zag-js/types\"\nimport { parts } from \"./clipboard.anatomy\"\nimport type { MachineApi, Send, State } from \"./clipboard.types\"\nimport { dom } from \"./clipboard.dom\"\n\nexport function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): MachineApi<T> {\n const isCopied = state.matches(\"copied\")\n\n return {\n isCopied,\n value: state.context.value,\n setValue(value) {\n send({ type: \"VALUE.SET\", value })\n },\n rootProps: normalize.element({\n ...parts.root.attrs,\n \"data-copied\": dataAttr(isCopied),\n id: dom.getRootId(state.context),\n }),\n labelProps: normalize.label({\n ...parts.label.attrs,\n htmlFor: dom.getInputId(state.context),\n \"data-copied\": dataAttr(isCopied),\n id: dom.getLabelId(state.context),\n }),\n controlProps: normalize.element({\n ...parts.control.attrs,\n \"data-copied\": dataAttr(isCopied),\n }),\n inputProps: normalize.input({\n ...parts.input.attrs,\n defaultValue: state.context.value,\n \"data-copied\": dataAttr(isCopied),\n readOnly: true,\n \"data-readonly\": \"true\",\n id: dom.getInputId(state.context),\n onFocus(event) {\n event.currentTarget.select()\n },\n }),\n triggerProps: normalize.button({\n ...parts.trigger.attrs,\n \"aria-label\": isCopied ? \"Copied to clipboard\" : \"Copy to clipboard\",\n \"data-copied\": dataAttr(isCopied),\n onClick() {\n send({ type: \"COPY\" })\n },\n }),\n getIndicatorProps(props) {\n return normalize.element({\n ...parts.indicator.attrs,\n hidden: props.copied !== isCopied,\n })\n },\n }\n}\n","import { createScope, getWindow } from \"@zag-js/dom-query\"\nimport { hasProp } from \"@zag-js/utils\"\nimport type { MachineContext as Ctx } from \"./clipboard.types\"\n\nexport const dom = createScope({\n getRootId: (ctx: Ctx) => `clip-${ctx.id}`,\n getInputId: (ctx: Ctx) => `clip-input-${ctx.id}`,\n getLabelId: (ctx: Ctx) => `clip-label-${ctx.id}`,\n getInputEl: (ctx: Ctx) => dom.getById<HTMLInputElement>(ctx, dom.getInputId(ctx)),\n writeToClipboard: (ctx: Ctx) => copyText(dom.getDoc(ctx), ctx.value),\n})\n\nfunction createNode(doc: Document, text: string): HTMLElement {\n const node = doc.createElement(\"pre\")\n Object.assign(node.style, {\n width: \"1px\",\n height: \"1px\",\n position: \"fixed\",\n top: \"5px\",\n })\n node.textContent = text\n return node\n}\n\nfunction copyNode(node: HTMLElement): Promise<void> {\n const win = getWindow(node)\n\n const selection = win.getSelection()\n\n if (selection == null) {\n return Promise.reject(new Error())\n }\n\n selection.removeAllRanges()\n\n const doc = node.ownerDocument\n\n const range = doc.createRange()\n range.selectNodeContents(node)\n selection.addRange(range)\n\n doc.execCommand(\"copy\")\n selection.removeAllRanges()\n\n return Promise.resolve()\n}\n\nfunction copyText(doc: Document, text: string): Promise<void> {\n const win = doc.defaultView || window\n\n if (hasProp(win.navigator, \"clipboard\")) {\n return win.navigator.clipboard.writeText(text)\n }\n\n if (!doc.body) {\n return Promise.reject(new Error())\n }\n\n const node = createNode(doc, text)\n\n doc.body.appendChild(node)\n copyNode(node)\n doc.body.removeChild(node)\n\n return Promise.resolve()\n}\n","import { createMachine } from \"@zag-js/core\"\nimport { compact } from \"@zag-js/utils\"\nimport { dom } from \"./clipboard.dom\"\nimport type { MachineContext, MachineState, UserDefinedContext } from \"./clipboard.types\"\n\nexport function machine(userContext: UserDefinedContext) {\n const ctx = compact(userContext)\n return createMachine<MachineContext, MachineState>(\n {\n id: \"clipboard\",\n initial: \"idle\",\n context: {\n value: \"\",\n timeout: 3000,\n ...ctx,\n },\n watch: {\n value: [\"syncInputElement\"],\n },\n on: {\n \"VALUE.SET\": {\n actions: [\"setValue\"],\n },\n },\n states: {\n idle: {\n on: {\n COPY: {\n target: \"copied\",\n actions: [\"copyToClipboard\", \"invokeOnCopied\"],\n },\n },\n },\n copied: {\n after: {\n COPY_TIMEOUT: \"idle\",\n },\n on: {\n COPY: {\n target: \"copied\",\n actions: [\"copyToClipboard\", \"invokeOnCopied\"],\n },\n },\n },\n },\n },\n {\n actions: {\n setValue(ctx, evt) {\n ctx.value = evt.value\n },\n copyToClipboard(ctx) {\n dom.writeToClipboard(ctx)\n },\n invokeOnCopied(ctx) {\n ctx.onCopyStatusChange?.({ copied: true })\n },\n syncInputElement(ctx) {\n dom.setValue(dom.getInputEl(ctx), ctx.value)\n },\n },\n delays: {\n COPY_TIMEOUT: (ctx) => ctx.timeout,\n },\n },\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,qBAA8B;AAEvB,IAAM,cAAU,8BAAc,WAAW,EAAE,MAAM,QAAQ,WAAW,WAAW,aAAa,SAAS,OAAO;AAE5G,IAAM,QAAQ,QAAQ,MAAM;;;ACJnC,IAAAA,oBAAyB;;;ACAzB,uBAAuC;AACvC,mBAAwB;AAGjB,IAAM,UAAM,8BAAY;AAAA,EAC7B,WAAW,CAAC,QAAa,QAAQ,IAAI,EAAE;AAAA,EACvC,YAAY,CAAC,QAAa,cAAc,IAAI,EAAE;AAAA,EAC9C,YAAY,CAAC,QAAa,cAAc,IAAI,EAAE;AAAA,EAC9C,YAAY,CAAC,QAAa,IAAI,QAA0B,KAAK,IAAI,WAAW,GAAG,CAAC;AAAA,EAChF,kBAAkB,CAAC,QAAa,SAAS,IAAI,OAAO,GAAG,GAAG,IAAI,KAAK;AACrE,CAAC;AAED,SAAS,WAAW,KAAe,MAA2B;AAC5D,QAAM,OAAO,IAAI,cAAc,KAAK;AACpC,SAAO,OAAO,KAAK,OAAO;AAAA,IACxB,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,KAAK;AAAA,EACP,CAAC;AACD,OAAK,cAAc;AACnB,SAAO;AACT;AAEA,SAAS,SAAS,MAAkC;AAClD,QAAM,UAAM,4BAAU,IAAI;AAE1B,QAAM,YAAY,IAAI,aAAa;AAEnC,MAAI,aAAa,MAAM;AACrB,WAAO,QAAQ,OAAO,IAAI,MAAM,CAAC;AAAA,EACnC;AAEA,YAAU,gBAAgB;AAE1B,QAAM,MAAM,KAAK;AAEjB,QAAM,QAAQ,IAAI,YAAY;AAC9B,QAAM,mBAAmB,IAAI;AAC7B,YAAU,SAAS,KAAK;AAExB,MAAI,YAAY,MAAM;AACtB,YAAU,gBAAgB;AAE1B,SAAO,QAAQ,QAAQ;AACzB;AAEA,SAAS,SAAS,KAAe,MAA6B;AAC5D,QAAM,MAAM,IAAI,eAAe;AAE/B,UAAI,sBAAQ,IAAI,WAAW,WAAW,GAAG;AACvC,WAAO,IAAI,UAAU,UAAU,UAAU,IAAI;AAAA,EAC/C;AAEA,MAAI,CAAC,IAAI,MAAM;AACb,WAAO,QAAQ,OAAO,IAAI,MAAM,CAAC;AAAA,EACnC;AAEA,QAAM,OAAO,WAAW,KAAK,IAAI;AAEjC,MAAI,KAAK,YAAY,IAAI;AACzB,WAAS,IAAI;AACb,MAAI,KAAK,YAAY,IAAI;AAEzB,SAAO,QAAQ,QAAQ;AACzB;;;AD3DO,SAAS,QAA6B,OAAc,MAAY,WAA6C;AAClH,QAAM,WAAW,MAAM,QAAQ,QAAQ;AAEvC,SAAO;AAAA,IACL;AAAA,IACA,OAAO,MAAM,QAAQ;AAAA,IACrB,SAAS,OAAO;AACd,WAAK,EAAE,MAAM,aAAa,MAAM,CAAC;AAAA,IACnC;AAAA,IACA,WAAW,UAAU,QAAQ;AAAA,MAC3B,GAAG,MAAM,KAAK;AAAA,MACd,mBAAe,4BAAS,QAAQ;AAAA,MAChC,IAAI,IAAI,UAAU,MAAM,OAAO;AAAA,IACjC,CAAC;AAAA,IACD,YAAY,UAAU,MAAM;AAAA,MAC1B,GAAG,MAAM,MAAM;AAAA,MACf,SAAS,IAAI,WAAW,MAAM,OAAO;AAAA,MACrC,mBAAe,4BAAS,QAAQ;AAAA,MAChC,IAAI,IAAI,WAAW,MAAM,OAAO;AAAA,IAClC,CAAC;AAAA,IACD,cAAc,UAAU,QAAQ;AAAA,MAC9B,GAAG,MAAM,QAAQ;AAAA,MACjB,mBAAe,4BAAS,QAAQ;AAAA,IAClC,CAAC;AAAA,IACD,YAAY,UAAU,MAAM;AAAA,MAC1B,GAAG,MAAM,MAAM;AAAA,MACf,cAAc,MAAM,QAAQ;AAAA,MAC5B,mBAAe,4BAAS,QAAQ;AAAA,MAChC,UAAU;AAAA,MACV,iBAAiB;AAAA,MACjB,IAAI,IAAI,WAAW,MAAM,OAAO;AAAA,MAChC,QAAQ,OAAO;AACb,cAAM,cAAc,OAAO;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,IACD,cAAc,UAAU,OAAO;AAAA,MAC7B,GAAG,MAAM,QAAQ;AAAA,MACjB,cAAc,WAAW,wBAAwB;AAAA,MACjD,mBAAe,4BAAS,QAAQ;AAAA,MAChC,UAAU;AACR,aAAK,EAAE,MAAM,OAAO,CAAC;AAAA,MACvB;AAAA,IACF,CAAC;AAAA,IACD,kBAAkB,OAAO;AACvB,aAAO,UAAU,QAAQ;AAAA,QACvB,GAAG,MAAM,UAAU;AAAA,QACnB,QAAQ,MAAM,WAAW;AAAA,MAC3B,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AExDA,kBAA8B;AAC9B,IAAAC,gBAAwB;AAIjB,SAAS,QAAQ,aAAiC;AACvD,QAAM,UAAM,uBAAQ,WAAW;AAC/B,aAAO;AAAA,IACL;AAAA,MACE,IAAI;AAAA,MACJ,SAAS;AAAA,MACT,SAAS;AAAA,QACP,OAAO;AAAA,QACP,SAAS;AAAA,QACT,GAAG;AAAA,MACL;AAAA,MACA,OAAO;AAAA,QACL,OAAO,CAAC,kBAAkB;AAAA,MAC5B;AAAA,MACA,IAAI;AAAA,QACF,aAAa;AAAA,UACX,SAAS,CAAC,UAAU;AAAA,QACtB;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,IAAI;AAAA,YACF,MAAM;AAAA,cACJ,QAAQ;AAAA,cACR,SAAS,CAAC,mBAAmB,gBAAgB;AAAA,YAC/C;AAAA,UACF;AAAA,QACF;AAAA,QACA,QAAQ;AAAA,UACN,OAAO;AAAA,YACL,cAAc;AAAA,UAChB;AAAA,UACA,IAAI;AAAA,YACF,MAAM;AAAA,cACJ,QAAQ;AAAA,cACR,SAAS,CAAC,mBAAmB,gBAAgB;AAAA,YAC/C;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,SAAS;AAAA,QACP,SAASC,MAAK,KAAK;AACjB,UAAAA,KAAI,QAAQ,IAAI;AAAA,QAClB;AAAA,QACA,gBAAgBA,MAAK;AACnB,cAAI,iBAAiBA,IAAG;AAAA,QAC1B;AAAA,QACA,eAAeA,MAAK;AAClB,UAAAA,KAAI,qBAAqB,EAAE,QAAQ,KAAK,CAAC;AAAA,QAC3C;AAAA,QACA,iBAAiBA,MAAK;AACpB,cAAI,SAAS,IAAI,WAAWA,IAAG,GAAGA,KAAI,KAAK;AAAA,QAC7C;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN,cAAc,CAACA,SAAQA,KAAI;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AACF;","names":["import_dom_query","import_utils","ctx"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/clipboard.anatomy.ts","../src/clipboard.connect.ts","../src/clipboard.dom.ts","../src/clipboard.machine.ts"],"sourcesContent":["export { anatomy } from \"./clipboard.anatomy\"\nexport { connect } from \"./clipboard.connect\"\nexport { machine } from \"./clipboard.machine\"\nexport type { UserDefinedContext as Context, ElementIds, CopyStatusDetails, IndicatorProps } from \"./clipboard.types\"\n","import { createAnatomy } from \"@zag-js/anatomy\"\n\nexport const anatomy = createAnatomy(\"clipboard\").parts(\"root\", \"control\", \"trigger\", \"indicator\", \"input\", \"label\")\n\nexport const parts = anatomy.build()\n","import { dataAttr } from \"@zag-js/dom-query\"\nimport type { NormalizeProps, PropTypes } from \"@zag-js/types\"\nimport { parts } from \"./clipboard.anatomy\"\nimport type { MachineApi, Send, State } from \"./clipboard.types\"\nimport { dom } from \"./clipboard.dom\"\n\nexport function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): MachineApi<T> {\n const isCopied = state.matches(\"copied\")\n\n return {\n isCopied,\n value: state.context.value,\n setValue(value) {\n send({ type: \"VALUE.SET\", value })\n },\n copy() {\n send({ type: \"COPY\" })\n },\n rootProps: normalize.element({\n ...parts.root.attrs,\n \"data-copied\": dataAttr(isCopied),\n id: dom.getRootId(state.context),\n }),\n labelProps: normalize.label({\n ...parts.label.attrs,\n htmlFor: dom.getInputId(state.context),\n \"data-copied\": dataAttr(isCopied),\n id: dom.getLabelId(state.context),\n }),\n controlProps: normalize.element({\n ...parts.control.attrs,\n \"data-copied\": dataAttr(isCopied),\n }),\n inputProps: normalize.input({\n ...parts.input.attrs,\n defaultValue: state.context.value,\n \"data-copied\": dataAttr(isCopied),\n readOnly: true,\n \"data-readonly\": \"true\",\n id: dom.getInputId(state.context),\n onFocus(event) {\n event.currentTarget.select()\n },\n onCopy() {\n send({ type: \"INPUT.COPY\" })\n },\n }),\n triggerProps: normalize.button({\n ...parts.trigger.attrs,\n \"aria-label\": isCopied ? \"Copied to clipboard\" : \"Copy to clipboard\",\n \"data-copied\": dataAttr(isCopied),\n onClick() {\n send({ type: \"COPY\" })\n },\n }),\n getIndicatorProps(props) {\n return normalize.element({\n ...parts.indicator.attrs,\n hidden: props.copied !== isCopied,\n })\n },\n }\n}\n","import { createScope, getWindow } from \"@zag-js/dom-query\"\nimport { hasProp } from \"@zag-js/utils\"\nimport type { MachineContext as Ctx } from \"./clipboard.types\"\n\nexport const dom = createScope({\n getRootId: (ctx: Ctx) => ctx.ids?.root ?? `clip-${ctx.id}`,\n getInputId: (ctx: Ctx) => ctx.ids?.input ?? `clip-input-${ctx.id}`,\n getLabelId: (ctx: Ctx) => ctx.ids?.label ?? `clip-label-${ctx.id}`,\n getInputEl: (ctx: Ctx) => dom.getById<HTMLInputElement>(ctx, dom.getInputId(ctx)),\n writeToClipboard: (ctx: Ctx) => copyText(dom.getDoc(ctx), ctx.value),\n})\n\nfunction createNode(doc: Document, text: string): HTMLElement {\n const node = doc.createElement(\"pre\")\n Object.assign(node.style, {\n width: \"1px\",\n height: \"1px\",\n position: \"fixed\",\n top: \"5px\",\n })\n node.textContent = text\n return node\n}\n\nfunction copyNode(node: HTMLElement): Promise<void> {\n const win = getWindow(node)\n\n const selection = win.getSelection()\n\n if (selection == null) {\n return Promise.reject(new Error())\n }\n\n selection.removeAllRanges()\n\n const doc = node.ownerDocument\n\n const range = doc.createRange()\n range.selectNodeContents(node)\n selection.addRange(range)\n\n doc.execCommand(\"copy\")\n selection.removeAllRanges()\n\n return Promise.resolve()\n}\n\nfunction copyText(doc: Document, text: string): Promise<void> {\n const win = doc.defaultView || window\n\n if (hasProp(win.navigator, \"clipboard\")) {\n return win.navigator.clipboard.writeText(text)\n }\n\n if (!doc.body) {\n return Promise.reject(new Error())\n }\n\n const node = createNode(doc, text)\n\n doc.body.appendChild(node)\n copyNode(node)\n doc.body.removeChild(node)\n\n return Promise.resolve()\n}\n","import { createMachine } from \"@zag-js/core\"\nimport { compact } from \"@zag-js/utils\"\nimport { dom } from \"./clipboard.dom\"\nimport type { MachineContext, MachineState, UserDefinedContext } from \"./clipboard.types\"\n\nexport function machine(userContext: UserDefinedContext) {\n const ctx = compact(userContext)\n return createMachine<MachineContext, MachineState>(\n {\n id: \"clipboard\",\n initial: \"idle\",\n context: {\n value: \"\",\n timeout: 3000,\n ...ctx,\n },\n watch: {\n value: [\"syncInputElement\"],\n },\n on: {\n \"VALUE.SET\": {\n actions: [\"setValue\"],\n },\n COPY: {\n target: \"copied\",\n actions: [\"copyToClipboard\", \"invokeOnCopied\"],\n },\n },\n states: {\n idle: {\n on: {\n \"INPUT.COPY\": {\n target: \"copied\",\n actions: [\"invokeOnCopied\"],\n },\n },\n },\n copied: {\n after: {\n COPY_TIMEOUT: \"idle\",\n },\n on: {\n COPY: {\n target: \"copied\",\n actions: [\"copyToClipboard\", \"invokeOnCopied\"],\n },\n \"INPUT.COPY\": {\n actions: [\"invokeOnCopied\"],\n },\n },\n },\n },\n },\n {\n actions: {\n setValue(ctx, evt) {\n ctx.value = evt.value\n },\n copyToClipboard(ctx) {\n dom.writeToClipboard(ctx)\n },\n invokeOnCopied(ctx) {\n ctx.onCopyStatusChange?.({ copied: true })\n },\n syncInputElement(ctx) {\n dom.setValue(dom.getInputEl(ctx), ctx.value)\n },\n },\n delays: {\n COPY_TIMEOUT: (ctx) => ctx.timeout,\n },\n },\n )\n}\n"],"mappings":"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","names":["import_dom_query","import_utils","ctx"]}
|
package/dist/index.mjs
CHANGED
|
@@ -10,9 +10,9 @@ import { dataAttr } from "@zag-js/dom-query";
|
|
|
10
10
|
import { createScope, getWindow } from "@zag-js/dom-query";
|
|
11
11
|
import { hasProp } from "@zag-js/utils";
|
|
12
12
|
var dom = createScope({
|
|
13
|
-
getRootId: (ctx) => `clip-${ctx.id}`,
|
|
14
|
-
getInputId: (ctx) => `clip-input-${ctx.id}`,
|
|
15
|
-
getLabelId: (ctx) => `clip-label-${ctx.id}`,
|
|
13
|
+
getRootId: (ctx) => ctx.ids?.root ?? `clip-${ctx.id}`,
|
|
14
|
+
getInputId: (ctx) => ctx.ids?.input ?? `clip-input-${ctx.id}`,
|
|
15
|
+
getLabelId: (ctx) => ctx.ids?.label ?? `clip-label-${ctx.id}`,
|
|
16
16
|
getInputEl: (ctx) => dom.getById(ctx, dom.getInputId(ctx)),
|
|
17
17
|
writeToClipboard: (ctx) => copyText(dom.getDoc(ctx), ctx.value)
|
|
18
18
|
});
|
|
@@ -66,6 +66,9 @@ function connect(state, send, normalize) {
|
|
|
66
66
|
setValue(value) {
|
|
67
67
|
send({ type: "VALUE.SET", value });
|
|
68
68
|
},
|
|
69
|
+
copy() {
|
|
70
|
+
send({ type: "COPY" });
|
|
71
|
+
},
|
|
69
72
|
rootProps: normalize.element({
|
|
70
73
|
...parts.root.attrs,
|
|
71
74
|
"data-copied": dataAttr(isCopied),
|
|
@@ -90,6 +93,9 @@ function connect(state, send, normalize) {
|
|
|
90
93
|
id: dom.getInputId(state.context),
|
|
91
94
|
onFocus(event) {
|
|
92
95
|
event.currentTarget.select();
|
|
96
|
+
},
|
|
97
|
+
onCopy() {
|
|
98
|
+
send({ type: "INPUT.COPY" });
|
|
93
99
|
}
|
|
94
100
|
}),
|
|
95
101
|
triggerProps: normalize.button({
|
|
@@ -129,14 +135,18 @@ function machine(userContext) {
|
|
|
129
135
|
on: {
|
|
130
136
|
"VALUE.SET": {
|
|
131
137
|
actions: ["setValue"]
|
|
138
|
+
},
|
|
139
|
+
COPY: {
|
|
140
|
+
target: "copied",
|
|
141
|
+
actions: ["copyToClipboard", "invokeOnCopied"]
|
|
132
142
|
}
|
|
133
143
|
},
|
|
134
144
|
states: {
|
|
135
145
|
idle: {
|
|
136
146
|
on: {
|
|
137
|
-
COPY: {
|
|
147
|
+
"INPUT.COPY": {
|
|
138
148
|
target: "copied",
|
|
139
|
-
actions: ["
|
|
149
|
+
actions: ["invokeOnCopied"]
|
|
140
150
|
}
|
|
141
151
|
}
|
|
142
152
|
},
|
|
@@ -148,6 +158,9 @@ function machine(userContext) {
|
|
|
148
158
|
COPY: {
|
|
149
159
|
target: "copied",
|
|
150
160
|
actions: ["copyToClipboard", "invokeOnCopied"]
|
|
161
|
+
},
|
|
162
|
+
"INPUT.COPY": {
|
|
163
|
+
actions: ["invokeOnCopied"]
|
|
151
164
|
}
|
|
152
165
|
}
|
|
153
166
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/clipboard.anatomy.ts","../src/clipboard.connect.ts","../src/clipboard.dom.ts","../src/clipboard.machine.ts"],"sourcesContent":["import { createAnatomy } from \"@zag-js/anatomy\"\n\nexport const anatomy = createAnatomy(\"clipboard\").parts(\"root\", \"control\", \"trigger\", \"indicator\", \"input\", \"label\")\n\nexport const parts = anatomy.build()\n","import { dataAttr } from \"@zag-js/dom-query\"\nimport type { NormalizeProps, PropTypes } from \"@zag-js/types\"\nimport { parts } from \"./clipboard.anatomy\"\nimport type { MachineApi, Send, State } from \"./clipboard.types\"\nimport { dom } from \"./clipboard.dom\"\n\nexport function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): MachineApi<T> {\n const isCopied = state.matches(\"copied\")\n\n return {\n isCopied,\n value: state.context.value,\n setValue(value) {\n send({ type: \"VALUE.SET\", value })\n },\n rootProps: normalize.element({\n ...parts.root.attrs,\n \"data-copied\": dataAttr(isCopied),\n id: dom.getRootId(state.context),\n }),\n labelProps: normalize.label({\n ...parts.label.attrs,\n htmlFor: dom.getInputId(state.context),\n \"data-copied\": dataAttr(isCopied),\n id: dom.getLabelId(state.context),\n }),\n controlProps: normalize.element({\n ...parts.control.attrs,\n \"data-copied\": dataAttr(isCopied),\n }),\n inputProps: normalize.input({\n ...parts.input.attrs,\n defaultValue: state.context.value,\n \"data-copied\": dataAttr(isCopied),\n readOnly: true,\n \"data-readonly\": \"true\",\n id: dom.getInputId(state.context),\n onFocus(event) {\n event.currentTarget.select()\n },\n }),\n triggerProps: normalize.button({\n ...parts.trigger.attrs,\n \"aria-label\": isCopied ? \"Copied to clipboard\" : \"Copy to clipboard\",\n \"data-copied\": dataAttr(isCopied),\n onClick() {\n send({ type: \"COPY\" })\n },\n }),\n getIndicatorProps(props) {\n return normalize.element({\n ...parts.indicator.attrs,\n hidden: props.copied !== isCopied,\n })\n },\n }\n}\n","import { createScope, getWindow } from \"@zag-js/dom-query\"\nimport { hasProp } from \"@zag-js/utils\"\nimport type { MachineContext as Ctx } from \"./clipboard.types\"\n\nexport const dom = createScope({\n getRootId: (ctx: Ctx) => `clip-${ctx.id}`,\n getInputId: (ctx: Ctx) => `clip-input-${ctx.id}`,\n getLabelId: (ctx: Ctx) => `clip-label-${ctx.id}`,\n getInputEl: (ctx: Ctx) => dom.getById<HTMLInputElement>(ctx, dom.getInputId(ctx)),\n writeToClipboard: (ctx: Ctx) => copyText(dom.getDoc(ctx), ctx.value),\n})\n\nfunction createNode(doc: Document, text: string): HTMLElement {\n const node = doc.createElement(\"pre\")\n Object.assign(node.style, {\n width: \"1px\",\n height: \"1px\",\n position: \"fixed\",\n top: \"5px\",\n })\n node.textContent = text\n return node\n}\n\nfunction copyNode(node: HTMLElement): Promise<void> {\n const win = getWindow(node)\n\n const selection = win.getSelection()\n\n if (selection == null) {\n return Promise.reject(new Error())\n }\n\n selection.removeAllRanges()\n\n const doc = node.ownerDocument\n\n const range = doc.createRange()\n range.selectNodeContents(node)\n selection.addRange(range)\n\n doc.execCommand(\"copy\")\n selection.removeAllRanges()\n\n return Promise.resolve()\n}\n\nfunction copyText(doc: Document, text: string): Promise<void> {\n const win = doc.defaultView || window\n\n if (hasProp(win.navigator, \"clipboard\")) {\n return win.navigator.clipboard.writeText(text)\n }\n\n if (!doc.body) {\n return Promise.reject(new Error())\n }\n\n const node = createNode(doc, text)\n\n doc.body.appendChild(node)\n copyNode(node)\n doc.body.removeChild(node)\n\n return Promise.resolve()\n}\n","import { createMachine } from \"@zag-js/core\"\nimport { compact } from \"@zag-js/utils\"\nimport { dom } from \"./clipboard.dom\"\nimport type { MachineContext, MachineState, UserDefinedContext } from \"./clipboard.types\"\n\nexport function machine(userContext: UserDefinedContext) {\n const ctx = compact(userContext)\n return createMachine<MachineContext, MachineState>(\n {\n id: \"clipboard\",\n initial: \"idle\",\n context: {\n value: \"\",\n timeout: 3000,\n ...ctx,\n },\n watch: {\n value: [\"syncInputElement\"],\n },\n on: {\n \"VALUE.SET\": {\n actions: [\"setValue\"],\n },\n },\n states: {\n idle: {\n on: {\n COPY: {\n target: \"copied\",\n actions: [\"
|
|
1
|
+
{"version":3,"sources":["../src/clipboard.anatomy.ts","../src/clipboard.connect.ts","../src/clipboard.dom.ts","../src/clipboard.machine.ts"],"sourcesContent":["import { createAnatomy } from \"@zag-js/anatomy\"\n\nexport const anatomy = createAnatomy(\"clipboard\").parts(\"root\", \"control\", \"trigger\", \"indicator\", \"input\", \"label\")\n\nexport const parts = anatomy.build()\n","import { dataAttr } from \"@zag-js/dom-query\"\nimport type { NormalizeProps, PropTypes } from \"@zag-js/types\"\nimport { parts } from \"./clipboard.anatomy\"\nimport type { MachineApi, Send, State } from \"./clipboard.types\"\nimport { dom } from \"./clipboard.dom\"\n\nexport function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): MachineApi<T> {\n const isCopied = state.matches(\"copied\")\n\n return {\n isCopied,\n value: state.context.value,\n setValue(value) {\n send({ type: \"VALUE.SET\", value })\n },\n copy() {\n send({ type: \"COPY\" })\n },\n rootProps: normalize.element({\n ...parts.root.attrs,\n \"data-copied\": dataAttr(isCopied),\n id: dom.getRootId(state.context),\n }),\n labelProps: normalize.label({\n ...parts.label.attrs,\n htmlFor: dom.getInputId(state.context),\n \"data-copied\": dataAttr(isCopied),\n id: dom.getLabelId(state.context),\n }),\n controlProps: normalize.element({\n ...parts.control.attrs,\n \"data-copied\": dataAttr(isCopied),\n }),\n inputProps: normalize.input({\n ...parts.input.attrs,\n defaultValue: state.context.value,\n \"data-copied\": dataAttr(isCopied),\n readOnly: true,\n \"data-readonly\": \"true\",\n id: dom.getInputId(state.context),\n onFocus(event) {\n event.currentTarget.select()\n },\n onCopy() {\n send({ type: \"INPUT.COPY\" })\n },\n }),\n triggerProps: normalize.button({\n ...parts.trigger.attrs,\n \"aria-label\": isCopied ? \"Copied to clipboard\" : \"Copy to clipboard\",\n \"data-copied\": dataAttr(isCopied),\n onClick() {\n send({ type: \"COPY\" })\n },\n }),\n getIndicatorProps(props) {\n return normalize.element({\n ...parts.indicator.attrs,\n hidden: props.copied !== isCopied,\n })\n },\n }\n}\n","import { createScope, getWindow } from \"@zag-js/dom-query\"\nimport { hasProp } from \"@zag-js/utils\"\nimport type { MachineContext as Ctx } from \"./clipboard.types\"\n\nexport const dom = createScope({\n getRootId: (ctx: Ctx) => ctx.ids?.root ?? `clip-${ctx.id}`,\n getInputId: (ctx: Ctx) => ctx.ids?.input ?? `clip-input-${ctx.id}`,\n getLabelId: (ctx: Ctx) => ctx.ids?.label ?? `clip-label-${ctx.id}`,\n getInputEl: (ctx: Ctx) => dom.getById<HTMLInputElement>(ctx, dom.getInputId(ctx)),\n writeToClipboard: (ctx: Ctx) => copyText(dom.getDoc(ctx), ctx.value),\n})\n\nfunction createNode(doc: Document, text: string): HTMLElement {\n const node = doc.createElement(\"pre\")\n Object.assign(node.style, {\n width: \"1px\",\n height: \"1px\",\n position: \"fixed\",\n top: \"5px\",\n })\n node.textContent = text\n return node\n}\n\nfunction copyNode(node: HTMLElement): Promise<void> {\n const win = getWindow(node)\n\n const selection = win.getSelection()\n\n if (selection == null) {\n return Promise.reject(new Error())\n }\n\n selection.removeAllRanges()\n\n const doc = node.ownerDocument\n\n const range = doc.createRange()\n range.selectNodeContents(node)\n selection.addRange(range)\n\n doc.execCommand(\"copy\")\n selection.removeAllRanges()\n\n return Promise.resolve()\n}\n\nfunction copyText(doc: Document, text: string): Promise<void> {\n const win = doc.defaultView || window\n\n if (hasProp(win.navigator, \"clipboard\")) {\n return win.navigator.clipboard.writeText(text)\n }\n\n if (!doc.body) {\n return Promise.reject(new Error())\n }\n\n const node = createNode(doc, text)\n\n doc.body.appendChild(node)\n copyNode(node)\n doc.body.removeChild(node)\n\n return Promise.resolve()\n}\n","import { createMachine } from \"@zag-js/core\"\nimport { compact } from \"@zag-js/utils\"\nimport { dom } from \"./clipboard.dom\"\nimport type { MachineContext, MachineState, UserDefinedContext } from \"./clipboard.types\"\n\nexport function machine(userContext: UserDefinedContext) {\n const ctx = compact(userContext)\n return createMachine<MachineContext, MachineState>(\n {\n id: \"clipboard\",\n initial: \"idle\",\n context: {\n value: \"\",\n timeout: 3000,\n ...ctx,\n },\n watch: {\n value: [\"syncInputElement\"],\n },\n on: {\n \"VALUE.SET\": {\n actions: [\"setValue\"],\n },\n COPY: {\n target: \"copied\",\n actions: [\"copyToClipboard\", \"invokeOnCopied\"],\n },\n },\n states: {\n idle: {\n on: {\n \"INPUT.COPY\": {\n target: \"copied\",\n actions: [\"invokeOnCopied\"],\n },\n },\n },\n copied: {\n after: {\n COPY_TIMEOUT: \"idle\",\n },\n on: {\n COPY: {\n target: \"copied\",\n actions: [\"copyToClipboard\", \"invokeOnCopied\"],\n },\n \"INPUT.COPY\": {\n actions: [\"invokeOnCopied\"],\n },\n },\n },\n },\n },\n {\n actions: {\n setValue(ctx, evt) {\n ctx.value = evt.value\n },\n copyToClipboard(ctx) {\n dom.writeToClipboard(ctx)\n },\n invokeOnCopied(ctx) {\n ctx.onCopyStatusChange?.({ copied: true })\n },\n syncInputElement(ctx) {\n dom.setValue(dom.getInputEl(ctx), ctx.value)\n },\n },\n delays: {\n COPY_TIMEOUT: (ctx) => ctx.timeout,\n },\n },\n )\n}\n"],"mappings":"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","names":["ctx"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zag-js/clipboard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.0",
|
|
4
4
|
"description": "Core logic for the clipboard widget implemented as a state machine",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"js",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"url": "https://github.com/chakra-ui/zag/issues"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@zag-js/anatomy": "0.
|
|
32
|
-
"@zag-js/core": "0.
|
|
33
|
-
"@zag-js/dom-query": "0.
|
|
34
|
-
"@zag-js/utils": "0.
|
|
35
|
-
"@zag-js/types": "0.
|
|
31
|
+
"@zag-js/anatomy": "0.36.0",
|
|
32
|
+
"@zag-js/core": "0.36.0",
|
|
33
|
+
"@zag-js/dom-query": "0.36.0",
|
|
34
|
+
"@zag-js/utils": "0.36.0",
|
|
35
|
+
"@zag-js/types": "0.36.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"clean-package": "2.2.0"
|
package/src/clipboard.connect.ts
CHANGED
|
@@ -13,6 +13,9 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
13
13
|
setValue(value) {
|
|
14
14
|
send({ type: "VALUE.SET", value })
|
|
15
15
|
},
|
|
16
|
+
copy() {
|
|
17
|
+
send({ type: "COPY" })
|
|
18
|
+
},
|
|
16
19
|
rootProps: normalize.element({
|
|
17
20
|
...parts.root.attrs,
|
|
18
21
|
"data-copied": dataAttr(isCopied),
|
|
@@ -38,6 +41,9 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
38
41
|
onFocus(event) {
|
|
39
42
|
event.currentTarget.select()
|
|
40
43
|
},
|
|
44
|
+
onCopy() {
|
|
45
|
+
send({ type: "INPUT.COPY" })
|
|
46
|
+
},
|
|
41
47
|
}),
|
|
42
48
|
triggerProps: normalize.button({
|
|
43
49
|
...parts.trigger.attrs,
|
package/src/clipboard.dom.ts
CHANGED
|
@@ -3,9 +3,9 @@ import { hasProp } from "@zag-js/utils"
|
|
|
3
3
|
import type { MachineContext as Ctx } from "./clipboard.types"
|
|
4
4
|
|
|
5
5
|
export const dom = createScope({
|
|
6
|
-
getRootId: (ctx: Ctx) => `clip-${ctx.id}`,
|
|
7
|
-
getInputId: (ctx: Ctx) => `clip-input-${ctx.id}`,
|
|
8
|
-
getLabelId: (ctx: Ctx) => `clip-label-${ctx.id}`,
|
|
6
|
+
getRootId: (ctx: Ctx) => ctx.ids?.root ?? `clip-${ctx.id}`,
|
|
7
|
+
getInputId: (ctx: Ctx) => ctx.ids?.input ?? `clip-input-${ctx.id}`,
|
|
8
|
+
getLabelId: (ctx: Ctx) => ctx.ids?.label ?? `clip-label-${ctx.id}`,
|
|
9
9
|
getInputEl: (ctx: Ctx) => dom.getById<HTMLInputElement>(ctx, dom.getInputId(ctx)),
|
|
10
10
|
writeToClipboard: (ctx: Ctx) => copyText(dom.getDoc(ctx), ctx.value),
|
|
11
11
|
})
|
package/src/clipboard.machine.ts
CHANGED
|
@@ -21,13 +21,17 @@ export function machine(userContext: UserDefinedContext) {
|
|
|
21
21
|
"VALUE.SET": {
|
|
22
22
|
actions: ["setValue"],
|
|
23
23
|
},
|
|
24
|
+
COPY: {
|
|
25
|
+
target: "copied",
|
|
26
|
+
actions: ["copyToClipboard", "invokeOnCopied"],
|
|
27
|
+
},
|
|
24
28
|
},
|
|
25
29
|
states: {
|
|
26
30
|
idle: {
|
|
27
31
|
on: {
|
|
28
|
-
COPY: {
|
|
32
|
+
"INPUT.COPY": {
|
|
29
33
|
target: "copied",
|
|
30
|
-
actions: ["
|
|
34
|
+
actions: ["invokeOnCopied"],
|
|
31
35
|
},
|
|
32
36
|
},
|
|
33
37
|
},
|
|
@@ -40,6 +44,9 @@ export function machine(userContext: UserDefinedContext) {
|
|
|
40
44
|
target: "copied",
|
|
41
45
|
actions: ["copyToClipboard", "invokeOnCopied"],
|
|
42
46
|
},
|
|
47
|
+
"INPUT.COPY": {
|
|
48
|
+
actions: ["invokeOnCopied"],
|
|
49
|
+
},
|
|
43
50
|
},
|
|
44
51
|
},
|
|
45
52
|
},
|
package/src/clipboard.types.ts
CHANGED
|
@@ -5,7 +5,17 @@ export interface CopyStatusDetails {
|
|
|
5
5
|
copied: boolean
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
export type ElementIds = Partial<{
|
|
9
|
+
root: string
|
|
10
|
+
input: string
|
|
11
|
+
label: string
|
|
12
|
+
}>
|
|
13
|
+
|
|
8
14
|
interface PublicContext extends CommonProperties {
|
|
15
|
+
/**
|
|
16
|
+
* The ids of the elements in the clipboard. Useful for composition.
|
|
17
|
+
*/
|
|
18
|
+
ids?: ElementIds
|
|
9
19
|
/**
|
|
10
20
|
* The value to be copied to the clipboard
|
|
11
21
|
*/
|
|
@@ -57,6 +67,10 @@ export interface MachineApi<T extends PropTypes = PropTypes> {
|
|
|
57
67
|
* Set the value to be copied to the clipboard
|
|
58
68
|
*/
|
|
59
69
|
setValue(value: string): void
|
|
70
|
+
/**
|
|
71
|
+
* Copy the value to the clipboard
|
|
72
|
+
*/
|
|
73
|
+
copy(): void
|
|
60
74
|
|
|
61
75
|
rootProps: T["element"]
|
|
62
76
|
labelProps: T["label"]
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { anatomy } from "./clipboard.anatomy"
|
|
2
2
|
export { connect } from "./clipboard.connect"
|
|
3
3
|
export { machine } from "./clipboard.machine"
|
|
4
|
-
export type { UserDefinedContext as Context } from "./clipboard.types"
|
|
4
|
+
export type { UserDefinedContext as Context, ElementIds, CopyStatusDetails, IndicatorProps } from "./clipboard.types"
|