@planningcenter/organization-avatars 1.6.3 → 1.7.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/README.md +32 -5
- package/dist/index.cjs +1 -1
- package/dist/index.js +213 -174
- package/dist/organization_avatar.d.ts +1 -1
- package/dist/style.css +24 -15
- package/dist/types.d.ts +1 -0
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -2,15 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
This package provides an `OrganizationAvatars` React component which encapsulates displaying and updating an organization's avatar.
|
|
4
4
|
|
|
5
|
-
See [the component's type signature](https://github.com/planningcenter/organization-avatars/blob/main/src/types.ts) for up-to-date props.
|
|
6
|
-
|
|
7
5
|
## Usage
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
```tsx
|
|
8
|
+
import { OrganizationAvatars } from "@planningcenter/organization-avatars"
|
|
9
|
+
import "@planningcenter/organization-avatars/style.css"
|
|
10
|
+
|
|
11
|
+
<OrganizationAvatars
|
|
12
|
+
orgName="Demo Church"
|
|
13
|
+
avatarUrl="https://example.com/avatar.png"
|
|
14
|
+
darkModeAvatarUrl="https://example.com/avatar-dark.png"
|
|
15
|
+
showDarkModeAvatar
|
|
16
|
+
onAvatarUpdate={(mode, newUrl) => console.log(mode, newUrl)}
|
|
17
|
+
/>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
To see a working example, see the [`/organization` page in Accounts](https://accounts.planningcenteronline.com/organization). The `OrganizationAvatars` component is mounted in [the `_church_information` partial](https://github.com/planningcenter/accounts/blob/main/app/views/organization/show/_church_information.html.erb).
|
|
21
|
+
|
|
22
|
+
## Props
|
|
23
|
+
|
|
24
|
+
| Prop | Type | Default | Description |
|
|
25
|
+
| --- | --- | --- | --- |
|
|
26
|
+
| `orgName` | `string` | **required** | The organization name, used for avatar alt text. |
|
|
27
|
+
| `avatarUrl` | `string` | `undefined` | URL of the current light mode avatar. When no `darkModeAvatarUrl` is provided, this is also used for the dark mode slot. |
|
|
28
|
+
| `darkModeAvatarUrl` | `string` | `undefined` | URL of the current dark mode avatar. Falls back to `avatarUrl` if not set. |
|
|
29
|
+
| `showDarkModeAvatar` | `boolean` | `false` | Whether to render the dark mode avatar UI alongside the light mode avatar. Intended to be controlled by a feature flag. |
|
|
30
|
+
| `onAvatarUpdate` | `(mode: AvatarMode, newUrl: string) => void` | `undefined` | Callback fired after a successful upload or delete. `mode` is `"avatar"` or `"dark_mode_avatar"`. `newUrl` is the new URL (or `""` on delete). |
|
|
31
|
+
| `pcoEnv` | `Environment` | `undefined` | Planning Center environment override (`"production"`, `"staging"`, `"development"`, `"test"`, `"prototype"`). When omitted, the environment is inferred automatically. |
|
|
32
|
+
| `readOnly` | `boolean` | `false` | Disables the edit button, preventing uploads and deletes. |
|
|
33
|
+
|
|
34
|
+
### Types
|
|
10
35
|
|
|
11
|
-
|
|
36
|
+
```ts
|
|
37
|
+
type AvatarMode = "avatar" | "dark_mode_avatar"
|
|
12
38
|
|
|
13
|
-
|
|
39
|
+
type Environment = "production" | "staging" | "development" | "test" | "prototype"
|
|
40
|
+
```
|
|
14
41
|
|
|
15
42
|
## Development
|
|
16
43
|
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),c=require("react"),T=require("react-dom"),$=require("@planningcenter/url"),b=require("@planningcenter/tapestry"),I=require("@planningcenter/sweetest-alert"),_=require("@planningcenter/icons/paths/general"),L=require("@planningcenter/icons/paths/services"),E=require("react-dropzone");function B(a){var r,t,o="";if(typeof a=="string"||typeof a=="number")o+=a;else if(typeof a=="object")if(Array.isArray(a)){var d=a.length;for(r=0;r<d;r++)a[r]&&(t=B(a[r]))&&(o&&(o+=" "),o+=t)}else for(t in a)a[t]&&(o&&(o+=" "),o+=t);return o}function W(){for(var a,r,t=0,o="",d=arguments.length;t<d;t++)(a=arguments[t])&&(r=B(a))&&(o&&(o+=" "),o+=r);return o}function G(){const a=document.querySelector('meta[name="csrf-token"]');if(!a||!a.content)throw new Error('CSRF token not found. Ensure your Rails application includes <meta name="csrf-token" content="..."> in the document head.');return a.content}function J(a){const r=a.split("");return[r.shift()?.toUpperCase(),r.join("")].join("")}const X=a=>a==="dark_mode_avatar"?"dark":"light",z=({open:a})=>e.jsxs("h2",{className:"pco-org-avatar__instructions",children:["Drag & drop your logo file to upload, or"," ",e.jsx(b.Button,{label:"browse",kind:"inline-text",onClick:r=>{r.stopPropagation(),a()}})]});function F({avatarUrl:a,organization:r,mode:t,pcoEnv:o,readOnly:d,onAvatarUpdate:x,fallbackAvatarUrl:A}){const[n,f]=c.useState(null),[l,y]=c.useState(!1),[i,p]=c.useState(!1),[u,w]=c.useState(""),q=c.useId(),v=c.useRef(null),g=X(t),m=a||A,D=h=>{const[s]=h;s&&f(Object.assign(s,{preview:URL.createObjectURL(s)}))};c.useEffect(()=>()=>{n?.preview&&(URL.revokeObjectURL(n.preview),w(""))},[n]);const S=async h=>{const s=await fetch($.pcoApiUrl("accounts",{env:o}),{method:"PATCH",headers:{"Content-Type":"application/json","X-CSRF-Token":G(),Accept:"application/json"},body:JSON.stringify({data:{attributes:h}})}),j=await s.json();if(!s.ok)throw j;return j},M=async h=>{if(h.preventDefault(),!(!n||l||i)){y(!0);try{const s=new FileReader,j=await new Promise((k,C)=>{s.onloadend=()=>k(s.result),s.onerror=C,s.readAsDataURL(n)}),N=await S({[t]:j,[`${t}_cache`]:""});f(null),x(t,N.data.attributes[t].url),v.current?.close()}catch{w("We were unable to save your avatar.")}finally{y(!1)}}},U=async()=>{l||i||(p(!0),I.SweetestAlert({type:"danger",title:"Remove this logo?",content:`Removing this logo will mean your light mode logo appear in ${g} mode. This cannot be undone.`,confirmButton:"Remove logo",onConfirm:async()=>{try{await S({[`remove_${t}`]:"1"}),x(t,""),v.current?.close()}catch{w("We were unable to delete your avatar.")}finally{p(!1)}},onCancel:()=>{p(!1)}}))},O=()=>{f(null),w("")};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"pco-org-avatar",children:[e.jsx("button",{type:"button",onClick:()=>v.current?.showModal(),disabled:d,className:`pco-org-avatar__button pco-org-avatar__button--${g}`,children:m?e.jsxs(e.Fragment,{children:[e.jsx("img",{src:m,alt:`Church logo for ${r}`}),e.jsx("div",{className:"tds-btn tds-btn--interaction tds-btn--icononly",children:e.jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"currentColor","aria-hidden":"true",children:e.jsx("path",{d:_.pencil})})})]}):e.jsxs(e.Fragment,{children:[e.jsx("svg",{width:"48",height:"48",viewBox:"0 0 16 16",fill:"currentColor","aria-hidden":"true",children:e.jsx("path",{d:L.image})}),e.jsx("div",{className:"tds-btn tds-btn--interaction tds-btn--icononly",children:e.jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"currentColor","aria-hidden":"true",children:e.jsx("path",{d:_.pencil})})})]})}),e.jsxs("div",{className:"pco-org-avatar__label",children:[J(g)," mode"]})]}),T.createPortal(e.jsx("dialog",{id:q,ref:v,className:"pco-org-avatar__dialog",onClose:O,children:e.jsxs("form",{onSubmit:M,children:[e.jsxs("div",{className:"pco-org-avatar__dialog-header",children:[e.jsxs("h1",{className:"pco-org-avatar__dialog-title",children:["Church logo — ",g," mode"]}),e.jsx("button",{type:"button",onClick:()=>v.current?.close(),className:"pco-org-avatar__dialog-close","aria-label":"Close modal",children:e.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"currentColor","aria-hidden":"true",children:e.jsx("path",{d:_.smallX})})})]}),e.jsxs("div",{className:"pco-org-avatar__dialog-body",children:[u&&e.jsxs("div",{role:"alert",className:"pco-org-avatar__dialog-alert",children:[e.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",className:"symbol","aria-hidden":"true",children:e.jsx("path",{d:_.exclamationTriangle})}),e.jsx("p",{children:u})]}),e.jsx(E,{accept:{"image/*":[".jpg",".jpeg",".png"]},multiple:!1,onDropAccepted:D,children:({getRootProps:h,getInputProps:s,isFocused:j,isDragAccept:N,isDragReject:k,isDragActive:C,open:R})=>{const P=W("pco-org-avatar__dialog-dropzone",`pco-org-avatar__dialog-dropzone--${g}`,{"pco-org-avatar__dialog-dropzone--image":n||m,"pco-org-avatar__dialog-dropzone--focused":j,"pco-org-avatar__dialog-dropzone--accepted":N,"pco-org-avatar__dialog-dropzone--rejected":C&&k});return e.jsxs(e.Fragment,{children:[e.jsxs("div",{...h({className:P}),children:[e.jsx("input",{...s()}),n?e.jsx("img",{src:n.preview,alt:`Church logo for ${r}`}):m?e.jsx("img",{src:m,alt:`Church logo for ${r}`}):e.jsxs(e.Fragment,{children:[e.jsx("svg",{width:"64",height:"64",viewBox:"0 0 16 16","aria-hidden":"true",children:e.jsx("path",{d:_.toCloudArrow})}),C&&k?e.jsxs(e.Fragment,{children:[e.jsx("h2",{children:"Wrong file type"}),e.jsx("p",{children:"Please upload a PNG or JPG file."})]}):e.jsxs(e.Fragment,{children:[e.jsx(z,{open:R}),e.jsx("p",{className:"pco-org-avatar__instructions-sub",children:"Use a high-quality image (up to 20mb) with a transparent background."})]})]})]}),(n||m)&&e.jsx(z,{open:R})]})}})]}),e.jsxs("div",{className:"pco-org-avatar__dialog-actions",children:[a&&g==="light"&&e.jsx(b.Button,{label:"Remove logo",kind:"secondary-delete",onClick:U,loading:i,disabled:i||l,className:"pco-org-avatar__dialog-delete"}),a&&g==="dark"&&e.jsx(b.Button,{label:"Use light mode logo",kind:"secondary",onClick:U,loading:i,disabled:i||l,className:"pco-org-avatar__dialog-delete"}),e.jsx(b.Button,{type:"button",label:"Cancel",onClick:()=>v.current?.close(),disabled:l||i}),e.jsx(b.Button,{type:"submit",label:"Update logo",kind:"primary",loading:l,disabled:!n||l||i})]})]})}),document.body)]})}function H({avatarUrl:a,darkModeAvatarUrl:r,orgName:t,onAvatarUpdate:o,pcoEnv:d,readOnly:x,showDarkModeAvatar:A=!1}){const[n,f]=c.useState(a),[l,y]=c.useState(r),i=(p,u)=>{p==="avatar"?(f(u),o?.("avatar",u)):p==="dark_mode_avatar"&&(y(u),o?.("dark_mode_avatar",u))};return e.jsxs("div",{className:"pco-org-avatars",children:[e.jsx(F,{avatarUrl:n,organization:t,mode:"avatar",pcoEnv:d,readOnly:x,onAvatarUpdate:i}),A&&e.jsx(F,{avatarUrl:l,organization:t,mode:"dark_mode_avatar",pcoEnv:d,readOnly:x,onAvatarUpdate:i,fallbackAvatarUrl:n})]})}exports.OrganizationAvatars=H;
|
package/dist/index.js
CHANGED
|
@@ -1,117 +1,140 @@
|
|
|
1
|
-
import { jsxs as n, Fragment as
|
|
2
|
-
import { useState as
|
|
3
|
-
import { createPortal as
|
|
4
|
-
import { pcoApiUrl as
|
|
5
|
-
import { Button as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
|
|
1
|
+
import { jsxs as n, Fragment as u, jsx as a } from "react/jsx-runtime";
|
|
2
|
+
import { useState as b, useId as L, useRef as E, useEffect as W } from "react";
|
|
3
|
+
import { createPortal as q } from "react-dom";
|
|
4
|
+
import { pcoApiUrl as G } from "@planningcenter/url";
|
|
5
|
+
import { Button as k } from "@planningcenter/tapestry";
|
|
6
|
+
import { SweetestAlert as J } from "@planningcenter/sweetest-alert";
|
|
7
|
+
import { pencil as B, smallX as X, exclamationTriangle as H, toCloudArrow as K } from "@planningcenter/icons/paths/general";
|
|
8
|
+
import { image as Q } from "@planningcenter/icons/paths/services";
|
|
9
|
+
import V from "react-dropzone";
|
|
10
|
+
function M(e) {
|
|
10
11
|
var o, r, t = "";
|
|
11
|
-
if (typeof
|
|
12
|
-
else if (typeof
|
|
13
|
-
var
|
|
14
|
-
for (o = 0; o <
|
|
15
|
-
} else for (r in
|
|
12
|
+
if (typeof e == "string" || typeof e == "number") t += e;
|
|
13
|
+
else if (typeof e == "object") if (Array.isArray(e)) {
|
|
14
|
+
var s = e.length;
|
|
15
|
+
for (o = 0; o < s; o++) e[o] && (r = M(e[o])) && (t && (t += " "), t += r);
|
|
16
|
+
} else for (r in e) e[r] && (t && (t += " "), t += r);
|
|
16
17
|
return t;
|
|
17
18
|
}
|
|
18
|
-
function
|
|
19
|
-
for (var
|
|
19
|
+
function Y() {
|
|
20
|
+
for (var e, o, r = 0, t = "", s = arguments.length; r < s; r++) (e = arguments[r]) && (o = M(e)) && (t && (t += " "), t += o);
|
|
20
21
|
return t;
|
|
21
22
|
}
|
|
22
|
-
function
|
|
23
|
-
const
|
|
24
|
-
if (!
|
|
23
|
+
function Z() {
|
|
24
|
+
const e = document.querySelector('meta[name="csrf-token"]');
|
|
25
|
+
if (!e || !e.content)
|
|
25
26
|
throw new Error(
|
|
26
27
|
'CSRF token not found. Ensure your Rails application includes <meta name="csrf-token" content="..."> in the document head.'
|
|
27
28
|
);
|
|
28
|
-
return
|
|
29
|
+
return e.content;
|
|
29
30
|
}
|
|
30
|
-
function
|
|
31
|
-
const o =
|
|
31
|
+
function aa(e) {
|
|
32
|
+
const o = e.split("");
|
|
32
33
|
return [o.shift()?.toUpperCase(), o.join("")].join("");
|
|
33
34
|
}
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const ea = (e) => e === "dark_mode_avatar" ? "dark" : "light", D = ({ open: e }) => /* @__PURE__ */ n("h2", { className: "pco-org-avatar__instructions", children: [
|
|
36
|
+
"Drag & drop your logo file to upload, or",
|
|
37
|
+
" ",
|
|
38
|
+
/* @__PURE__ */ a(
|
|
39
|
+
k,
|
|
40
|
+
{
|
|
41
|
+
label: "browse",
|
|
42
|
+
kind: "inline-text",
|
|
43
|
+
onClick: (o) => {
|
|
44
|
+
o.stopPropagation(), e();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
] });
|
|
49
|
+
function F({
|
|
50
|
+
avatarUrl: e,
|
|
37
51
|
organization: o,
|
|
38
52
|
mode: r,
|
|
39
53
|
pcoEnv: t,
|
|
40
|
-
readOnly:
|
|
41
|
-
onAvatarUpdate:
|
|
54
|
+
readOnly: s,
|
|
55
|
+
onAvatarUpdate: y,
|
|
56
|
+
fallbackAvatarUrl: R
|
|
42
57
|
}) {
|
|
43
|
-
const [
|
|
44
|
-
const [
|
|
45
|
-
|
|
46
|
-
Object.assign(
|
|
47
|
-
preview: URL.createObjectURL(
|
|
58
|
+
const [i, w] = b(null), [d, C] = b(!1), [c, m] = b(!1), [g, A] = b(""), $ = L(), v = E(null), h = ea(r), f = e || R, P = (p) => {
|
|
59
|
+
const [l] = p;
|
|
60
|
+
l && w(
|
|
61
|
+
Object.assign(l, {
|
|
62
|
+
preview: URL.createObjectURL(l)
|
|
48
63
|
})
|
|
49
64
|
);
|
|
50
65
|
};
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}, [
|
|
54
|
-
const
|
|
55
|
-
const
|
|
66
|
+
W(() => () => {
|
|
67
|
+
i?.preview && (URL.revokeObjectURL(i.preview), A(""));
|
|
68
|
+
}, [i]);
|
|
69
|
+
const z = async (p) => {
|
|
70
|
+
const l = await fetch(G("accounts", { env: t }), {
|
|
56
71
|
method: "PATCH",
|
|
57
72
|
headers: {
|
|
58
73
|
"Content-Type": "application/json",
|
|
59
|
-
"X-CSRF-Token":
|
|
74
|
+
"X-CSRF-Token": Z(),
|
|
60
75
|
Accept: "application/json"
|
|
61
76
|
},
|
|
62
77
|
body: JSON.stringify({
|
|
63
78
|
data: {
|
|
64
|
-
attributes:
|
|
79
|
+
attributes: p
|
|
65
80
|
}
|
|
66
81
|
})
|
|
67
|
-
}),
|
|
68
|
-
if (!
|
|
69
|
-
return
|
|
70
|
-
},
|
|
71
|
-
if (
|
|
72
|
-
|
|
82
|
+
}), _ = await l.json();
|
|
83
|
+
if (!l.ok) throw _;
|
|
84
|
+
return _;
|
|
85
|
+
}, T = async (p) => {
|
|
86
|
+
if (p.preventDefault(), !(!i || d || c)) {
|
|
87
|
+
C(!0);
|
|
73
88
|
try {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
}), j = await
|
|
77
|
-
[r]:
|
|
89
|
+
const l = new FileReader(), _ = await new Promise((N, U) => {
|
|
90
|
+
l.onloadend = () => N(l.result), l.onerror = U, l.readAsDataURL(i);
|
|
91
|
+
}), j = await z({
|
|
92
|
+
[r]: _,
|
|
78
93
|
[`${r}_cache`]: ""
|
|
79
94
|
});
|
|
80
|
-
|
|
95
|
+
w(null), y(r, j.data.attributes[r].url), v.current?.close();
|
|
81
96
|
} catch {
|
|
82
|
-
|
|
97
|
+
A("We were unable to save your avatar.");
|
|
83
98
|
} finally {
|
|
84
|
-
|
|
99
|
+
C(!1);
|
|
85
100
|
}
|
|
86
101
|
}
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
102
|
+
}, x = async () => {
|
|
103
|
+
d || c || (m(!0), J({
|
|
104
|
+
type: "danger",
|
|
105
|
+
title: "Remove this logo?",
|
|
106
|
+
content: `Removing this logo will mean your light mode logo appear in ${h} mode. This cannot be undone.`,
|
|
107
|
+
confirmButton: "Remove logo",
|
|
108
|
+
onConfirm: async () => {
|
|
109
|
+
try {
|
|
110
|
+
await z({
|
|
111
|
+
[`remove_${r}`]: "1"
|
|
112
|
+
}), y(r, ""), v.current?.close();
|
|
113
|
+
} catch {
|
|
114
|
+
A("We were unable to delete your avatar.");
|
|
115
|
+
} finally {
|
|
116
|
+
m(!1);
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
onCancel: () => {
|
|
120
|
+
m(!1);
|
|
98
121
|
}
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
|
|
122
|
+
}));
|
|
123
|
+
}, O = () => {
|
|
124
|
+
w(null), A("");
|
|
102
125
|
};
|
|
103
|
-
return /* @__PURE__ */ n(
|
|
126
|
+
return /* @__PURE__ */ n(u, { children: [
|
|
104
127
|
/* @__PURE__ */ n("div", { className: "pco-org-avatar", children: [
|
|
105
|
-
/* @__PURE__ */
|
|
128
|
+
/* @__PURE__ */ a(
|
|
106
129
|
"button",
|
|
107
130
|
{
|
|
108
131
|
type: "button",
|
|
109
|
-
onClick: () =>
|
|
110
|
-
disabled:
|
|
111
|
-
className: `pco-org-avatar__button pco-org-avatar__button--${
|
|
112
|
-
children:
|
|
113
|
-
/* @__PURE__ */
|
|
114
|
-
/* @__PURE__ */
|
|
132
|
+
onClick: () => v.current?.showModal(),
|
|
133
|
+
disabled: s,
|
|
134
|
+
className: `pco-org-avatar__button pco-org-avatar__button--${h}`,
|
|
135
|
+
children: f ? /* @__PURE__ */ n(u, { children: [
|
|
136
|
+
/* @__PURE__ */ a("img", { src: f, alt: `Church logo for ${o}` }),
|
|
137
|
+
/* @__PURE__ */ a("div", { className: "tds-btn tds-btn--interaction tds-btn--icononly", children: /* @__PURE__ */ a(
|
|
115
138
|
"svg",
|
|
116
139
|
{
|
|
117
140
|
width: "14",
|
|
@@ -119,11 +142,11 @@ function D({
|
|
|
119
142
|
viewBox: "0 0 16 16",
|
|
120
143
|
fill: "currentColor",
|
|
121
144
|
"aria-hidden": "true",
|
|
122
|
-
children: /* @__PURE__ */
|
|
145
|
+
children: /* @__PURE__ */ a("path", { d: B })
|
|
123
146
|
}
|
|
124
147
|
) })
|
|
125
|
-
] }) : /* @__PURE__ */ n(
|
|
126
|
-
/* @__PURE__ */
|
|
148
|
+
] }) : /* @__PURE__ */ n(u, { children: [
|
|
149
|
+
/* @__PURE__ */ a(
|
|
127
150
|
"svg",
|
|
128
151
|
{
|
|
129
152
|
width: "48",
|
|
@@ -131,10 +154,10 @@ function D({
|
|
|
131
154
|
viewBox: "0 0 16 16",
|
|
132
155
|
fill: "currentColor",
|
|
133
156
|
"aria-hidden": "true",
|
|
134
|
-
children: /* @__PURE__ */
|
|
157
|
+
children: /* @__PURE__ */ a("path", { d: Q })
|
|
135
158
|
}
|
|
136
159
|
),
|
|
137
|
-
/* @__PURE__ */
|
|
160
|
+
/* @__PURE__ */ a("div", { className: "tds-btn tds-btn--interaction tds-btn--icononly", children: /* @__PURE__ */ a(
|
|
138
161
|
"svg",
|
|
139
162
|
{
|
|
140
163
|
width: "14",
|
|
@@ -142,40 +165,40 @@ function D({
|
|
|
142
165
|
viewBox: "0 0 16 16",
|
|
143
166
|
fill: "currentColor",
|
|
144
167
|
"aria-hidden": "true",
|
|
145
|
-
children: /* @__PURE__ */
|
|
168
|
+
children: /* @__PURE__ */ a("path", { d: B })
|
|
146
169
|
}
|
|
147
170
|
) })
|
|
148
171
|
] })
|
|
149
172
|
}
|
|
150
173
|
),
|
|
151
174
|
/* @__PURE__ */ n("div", { className: "pco-org-avatar__label", children: [
|
|
152
|
-
|
|
175
|
+
aa(h),
|
|
153
176
|
" mode"
|
|
154
177
|
] })
|
|
155
178
|
] }),
|
|
156
|
-
|
|
157
|
-
/* @__PURE__ */
|
|
179
|
+
q(
|
|
180
|
+
/* @__PURE__ */ a(
|
|
158
181
|
"dialog",
|
|
159
182
|
{
|
|
160
|
-
id:
|
|
161
|
-
ref:
|
|
183
|
+
id: $,
|
|
184
|
+
ref: v,
|
|
162
185
|
className: "pco-org-avatar__dialog",
|
|
163
|
-
onClose:
|
|
164
|
-
children: /* @__PURE__ */ n("form", { onSubmit:
|
|
186
|
+
onClose: O,
|
|
187
|
+
children: /* @__PURE__ */ n("form", { onSubmit: T, children: [
|
|
165
188
|
/* @__PURE__ */ n("div", { className: "pco-org-avatar__dialog-header", children: [
|
|
166
189
|
/* @__PURE__ */ n("h1", { className: "pco-org-avatar__dialog-title", children: [
|
|
167
190
|
"Church logo — ",
|
|
168
|
-
|
|
191
|
+
h,
|
|
169
192
|
" mode"
|
|
170
193
|
] }),
|
|
171
|
-
/* @__PURE__ */
|
|
194
|
+
/* @__PURE__ */ a(
|
|
172
195
|
"button",
|
|
173
196
|
{
|
|
174
197
|
type: "button",
|
|
175
|
-
onClick: () =>
|
|
198
|
+
onClick: () => v.current?.close(),
|
|
176
199
|
className: "pco-org-avatar__dialog-close",
|
|
177
200
|
"aria-label": "Close modal",
|
|
178
|
-
children: /* @__PURE__ */
|
|
201
|
+
children: /* @__PURE__ */ a(
|
|
179
202
|
"svg",
|
|
180
203
|
{
|
|
181
204
|
width: "16",
|
|
@@ -183,15 +206,15 @@ function D({
|
|
|
183
206
|
viewBox: "0 0 16 16",
|
|
184
207
|
fill: "currentColor",
|
|
185
208
|
"aria-hidden": "true",
|
|
186
|
-
children: /* @__PURE__ */
|
|
209
|
+
children: /* @__PURE__ */ a("path", { d: X })
|
|
187
210
|
}
|
|
188
211
|
)
|
|
189
212
|
}
|
|
190
213
|
)
|
|
191
214
|
] }),
|
|
192
215
|
/* @__PURE__ */ n("div", { className: "pco-org-avatar__dialog-body", children: [
|
|
193
|
-
|
|
194
|
-
/* @__PURE__ */
|
|
216
|
+
g && /* @__PURE__ */ n("div", { role: "alert", className: "pco-org-avatar__dialog-alert", children: [
|
|
217
|
+
/* @__PURE__ */ a(
|
|
195
218
|
"svg",
|
|
196
219
|
{
|
|
197
220
|
width: "16",
|
|
@@ -199,102 +222,117 @@ function D({
|
|
|
199
222
|
viewBox: "0 0 16 16",
|
|
200
223
|
className: "symbol",
|
|
201
224
|
"aria-hidden": "true",
|
|
202
|
-
children: /* @__PURE__ */
|
|
225
|
+
children: /* @__PURE__ */ a("path", { d: H })
|
|
203
226
|
}
|
|
204
227
|
),
|
|
205
|
-
/* @__PURE__ */
|
|
228
|
+
/* @__PURE__ */ a("p", { children: g })
|
|
206
229
|
] }),
|
|
207
|
-
/* @__PURE__ */
|
|
208
|
-
|
|
230
|
+
/* @__PURE__ */ a(
|
|
231
|
+
V,
|
|
209
232
|
{
|
|
210
233
|
accept: { "image/*": [".jpg", ".jpeg", ".png"] },
|
|
211
234
|
multiple: !1,
|
|
212
|
-
onDropAccepted:
|
|
235
|
+
onDropAccepted: P,
|
|
213
236
|
children: ({
|
|
214
|
-
getRootProps:
|
|
215
|
-
getInputProps:
|
|
216
|
-
isFocused:
|
|
237
|
+
getRootProps: p,
|
|
238
|
+
getInputProps: l,
|
|
239
|
+
isFocused: _,
|
|
217
240
|
isDragAccept: j,
|
|
218
|
-
isDragReject:
|
|
219
|
-
isDragActive:
|
|
241
|
+
isDragReject: N,
|
|
242
|
+
isDragActive: U,
|
|
243
|
+
open: S
|
|
220
244
|
}) => {
|
|
221
|
-
const
|
|
245
|
+
const I = Y(
|
|
222
246
|
"pco-org-avatar__dialog-dropzone",
|
|
223
|
-
`pco-org-avatar__dialog-dropzone--${
|
|
247
|
+
`pco-org-avatar__dialog-dropzone--${h}`,
|
|
224
248
|
{
|
|
225
|
-
"pco-org-avatar__dialog-dropzone--image":
|
|
226
|
-
"pco-org-avatar__dialog-dropzone--focused":
|
|
249
|
+
"pco-org-avatar__dialog-dropzone--image": i || f,
|
|
250
|
+
"pco-org-avatar__dialog-dropzone--focused": _,
|
|
227
251
|
"pco-org-avatar__dialog-dropzone--accepted": j,
|
|
228
|
-
"pco-org-avatar__dialog-dropzone--rejected":
|
|
252
|
+
"pco-org-avatar__dialog-dropzone--rejected": U && N
|
|
229
253
|
}
|
|
230
254
|
);
|
|
231
|
-
return /* @__PURE__ */ n(
|
|
232
|
-
/* @__PURE__ */
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
src: l.preview,
|
|
237
|
-
alt: `Church logo for ${o}`
|
|
238
|
-
}
|
|
239
|
-
) : a ? /* @__PURE__ */ e(
|
|
240
|
-
"img",
|
|
241
|
-
{
|
|
242
|
-
src: a,
|
|
243
|
-
alt: `Church logo for ${o}`
|
|
244
|
-
}
|
|
245
|
-
) : /* @__PURE__ */ n(f, { children: [
|
|
246
|
-
/* @__PURE__ */ e(
|
|
247
|
-
"svg",
|
|
255
|
+
return /* @__PURE__ */ n(u, { children: [
|
|
256
|
+
/* @__PURE__ */ n("div", { ...p({ className: I }), children: [
|
|
257
|
+
/* @__PURE__ */ a("input", { ...l() }),
|
|
258
|
+
i ? /* @__PURE__ */ a(
|
|
259
|
+
"img",
|
|
248
260
|
{
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
viewBox: "0 0 16 16",
|
|
252
|
-
"aria-hidden": "true",
|
|
253
|
-
children: /* @__PURE__ */ e("path", { d: q })
|
|
261
|
+
src: i.preview,
|
|
262
|
+
alt: `Church logo for ${o}`
|
|
254
263
|
}
|
|
255
|
-
)
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
264
|
+
) : f ? /* @__PURE__ */ a(
|
|
265
|
+
"img",
|
|
266
|
+
{
|
|
267
|
+
src: f,
|
|
268
|
+
alt: `Church logo for ${o}`
|
|
269
|
+
}
|
|
270
|
+
) : /* @__PURE__ */ n(u, { children: [
|
|
271
|
+
/* @__PURE__ */ a(
|
|
272
|
+
"svg",
|
|
273
|
+
{
|
|
274
|
+
width: "64",
|
|
275
|
+
height: "64",
|
|
276
|
+
viewBox: "0 0 16 16",
|
|
277
|
+
"aria-hidden": "true",
|
|
278
|
+
children: /* @__PURE__ */ a("path", { d: K })
|
|
279
|
+
}
|
|
280
|
+
),
|
|
281
|
+
U && N ? /* @__PURE__ */ n(u, { children: [
|
|
282
|
+
/* @__PURE__ */ a("h2", { children: "Wrong file type" }),
|
|
283
|
+
/* @__PURE__ */ a("p", { children: "Please upload a PNG or JPG file." })
|
|
284
|
+
] }) : /* @__PURE__ */ n(u, { children: [
|
|
285
|
+
/* @__PURE__ */ a(D, { open: S }),
|
|
286
|
+
/* @__PURE__ */ a("p", { className: "pco-org-avatar__instructions-sub", children: "Use a high-quality image (up to 20mb) with a transparent background." })
|
|
287
|
+
] })
|
|
262
288
|
] })
|
|
263
|
-
] })
|
|
289
|
+
] }),
|
|
290
|
+
(i || f) && /* @__PURE__ */ a(D, { open: S })
|
|
264
291
|
] });
|
|
265
292
|
}
|
|
266
293
|
}
|
|
267
294
|
)
|
|
268
295
|
] }),
|
|
269
296
|
/* @__PURE__ */ n("div", { className: "pco-org-avatar__dialog-actions", children: [
|
|
270
|
-
|
|
271
|
-
|
|
297
|
+
e && h === "light" && /* @__PURE__ */ a(
|
|
298
|
+
k,
|
|
272
299
|
{
|
|
273
|
-
label: "
|
|
274
|
-
kind: "delete",
|
|
275
|
-
onClick:
|
|
276
|
-
loading:
|
|
277
|
-
disabled:
|
|
300
|
+
label: "Remove logo",
|
|
301
|
+
kind: "secondary-delete",
|
|
302
|
+
onClick: x,
|
|
303
|
+
loading: c,
|
|
304
|
+
disabled: c || d,
|
|
278
305
|
className: "pco-org-avatar__dialog-delete"
|
|
279
306
|
}
|
|
280
307
|
),
|
|
281
|
-
/* @__PURE__ */
|
|
282
|
-
|
|
308
|
+
e && h === "dark" && /* @__PURE__ */ a(
|
|
309
|
+
k,
|
|
310
|
+
{
|
|
311
|
+
label: "Use light mode logo",
|
|
312
|
+
kind: "secondary",
|
|
313
|
+
onClick: x,
|
|
314
|
+
loading: c,
|
|
315
|
+
disabled: c || d,
|
|
316
|
+
className: "pco-org-avatar__dialog-delete"
|
|
317
|
+
}
|
|
318
|
+
),
|
|
319
|
+
/* @__PURE__ */ a(
|
|
320
|
+
k,
|
|
283
321
|
{
|
|
284
322
|
type: "button",
|
|
285
323
|
label: "Cancel",
|
|
286
|
-
onClick: () =>
|
|
287
|
-
disabled: d ||
|
|
324
|
+
onClick: () => v.current?.close(),
|
|
325
|
+
disabled: d || c
|
|
288
326
|
}
|
|
289
327
|
),
|
|
290
|
-
/* @__PURE__ */
|
|
291
|
-
|
|
328
|
+
/* @__PURE__ */ a(
|
|
329
|
+
k,
|
|
292
330
|
{
|
|
293
331
|
type: "submit",
|
|
294
332
|
label: "Update logo",
|
|
295
333
|
kind: "primary",
|
|
296
334
|
loading: d,
|
|
297
|
-
disabled: !
|
|
335
|
+
disabled: !i || d || c
|
|
298
336
|
}
|
|
299
337
|
)
|
|
300
338
|
] })
|
|
@@ -305,45 +343,46 @@ function D({
|
|
|
305
343
|
)
|
|
306
344
|
] });
|
|
307
345
|
}
|
|
308
|
-
function
|
|
309
|
-
avatarUrl:
|
|
346
|
+
function ga({
|
|
347
|
+
avatarUrl: e,
|
|
310
348
|
darkModeAvatarUrl: o,
|
|
311
349
|
orgName: r,
|
|
312
350
|
onAvatarUpdate: t,
|
|
313
|
-
pcoEnv:
|
|
314
|
-
readOnly:
|
|
315
|
-
showDarkModeAvatar:
|
|
351
|
+
pcoEnv: s,
|
|
352
|
+
readOnly: y,
|
|
353
|
+
showDarkModeAvatar: R = !1
|
|
316
354
|
}) {
|
|
317
|
-
const [
|
|
355
|
+
const [i, w] = b(e), [d, C] = b(
|
|
318
356
|
o
|
|
319
|
-
),
|
|
320
|
-
|
|
357
|
+
), c = (m, g) => {
|
|
358
|
+
m === "avatar" ? (w(g), t?.("avatar", g)) : m === "dark_mode_avatar" && (C(g), t?.("dark_mode_avatar", g));
|
|
321
359
|
};
|
|
322
360
|
return /* @__PURE__ */ n("div", { className: "pco-org-avatars", children: [
|
|
323
|
-
/* @__PURE__ */
|
|
324
|
-
|
|
361
|
+
/* @__PURE__ */ a(
|
|
362
|
+
F,
|
|
325
363
|
{
|
|
326
|
-
avatarUrl:
|
|
364
|
+
avatarUrl: i,
|
|
327
365
|
organization: r,
|
|
328
366
|
mode: "avatar",
|
|
329
|
-
pcoEnv:
|
|
330
|
-
readOnly:
|
|
331
|
-
onAvatarUpdate:
|
|
367
|
+
pcoEnv: s,
|
|
368
|
+
readOnly: y,
|
|
369
|
+
onAvatarUpdate: c
|
|
332
370
|
}
|
|
333
371
|
),
|
|
334
|
-
|
|
335
|
-
|
|
372
|
+
R && /* @__PURE__ */ a(
|
|
373
|
+
F,
|
|
336
374
|
{
|
|
337
|
-
avatarUrl:
|
|
375
|
+
avatarUrl: d,
|
|
338
376
|
organization: r,
|
|
339
377
|
mode: "dark_mode_avatar",
|
|
340
|
-
pcoEnv:
|
|
341
|
-
readOnly:
|
|
342
|
-
onAvatarUpdate:
|
|
378
|
+
pcoEnv: s,
|
|
379
|
+
readOnly: y,
|
|
380
|
+
onAvatarUpdate: c,
|
|
381
|
+
fallbackAvatarUrl: i
|
|
343
382
|
}
|
|
344
383
|
)
|
|
345
384
|
] });
|
|
346
385
|
}
|
|
347
386
|
export {
|
|
348
|
-
|
|
387
|
+
ga as OrganizationAvatars
|
|
349
388
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { OrganizationAvatarProps } from "./types";
|
|
2
|
-
export declare function OrganizationAvatar({ avatarUrl, organization, mode, pcoEnv, readOnly, onAvatarUpdate, }: OrganizationAvatarProps): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function OrganizationAvatar({ avatarUrl, organization, mode, pcoEnv, readOnly, onAvatarUpdate, fallbackAvatarUrl, }: OrganizationAvatarProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/style.css
CHANGED
|
@@ -178,19 +178,6 @@
|
|
|
178
178
|
fill: var(--t-icon-color-status-info);
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
.pco-org-avatar__dialog-dropzone h2 {
|
|
182
|
-
color: var(--t-text-color-headline);
|
|
183
|
-
font-size: var(--t-font-size-md);
|
|
184
|
-
font-weight: var(--t-font-weight-normal);
|
|
185
|
-
margin: 0;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
.pco-org-avatar__dialog-dropzone p {
|
|
189
|
-
color: var(--t-text-color-placeholder);
|
|
190
|
-
font-size: var(--t-font-size-sm);
|
|
191
|
-
margin: 0;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
181
|
.pco-org-avatar__dialog-dropzone img {
|
|
195
182
|
max-height: 100%;
|
|
196
183
|
max-width: 100%;
|
|
@@ -222,11 +209,25 @@
|
|
|
222
209
|
fill: var(--t-fill-color-status-error);
|
|
223
210
|
}
|
|
224
211
|
|
|
225
|
-
|
|
212
|
+
.pco-org-avatar__instructions {
|
|
213
|
+
font-size: var(--t-font-size-md);
|
|
214
|
+
font-weight: var(--t-font-weight-normal);
|
|
215
|
+
margin: var(--t-spacing-2) 0 0;
|
|
216
|
+
text-align: center;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.pco-org-avatar__instructions-sub {
|
|
220
|
+
color: var(--t-text-color-secondary);
|
|
221
|
+
font-size: var(--t-font-size-sm);
|
|
222
|
+
margin: 0;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/* Light/dark colors/backgrounds are hardcoded to match the avatar preview context,
|
|
226
226
|
regardless of the UI theme or whether an avatar is uploaded */
|
|
227
|
+
|
|
227
228
|
.pco-org-avatar__button--light,
|
|
228
229
|
.pco-org-avatar__dialog-dropzone--light {
|
|
229
|
-
background: hsl(0, 0%,
|
|
230
|
+
background: hsl(0, 0%, 97%);
|
|
230
231
|
}
|
|
231
232
|
|
|
232
233
|
.pco-org-avatar__button--light:has(img),
|
|
@@ -243,3 +244,11 @@
|
|
|
243
244
|
.pco-org-avatar__dialog-dropzone--dark:has(img) {
|
|
244
245
|
border-color: transparent;
|
|
245
246
|
}
|
|
247
|
+
|
|
248
|
+
.pco-org-avatar__dialog-dropzone--light .pco-org-avatar__instructions {
|
|
249
|
+
color: hsl(0, 0%, 12%);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.pco-org-avatar__dialog-dropzone--dark .pco-org-avatar__instructions {
|
|
253
|
+
color: hsl(0, 0%, 94%);
|
|
254
|
+
}
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/organization-avatars",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Organization avatar upload components for Planning Center apps",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "yarn@1.22.22",
|
|
@@ -31,14 +31,19 @@
|
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@planningcenter/icons": "^15.29.1",
|
|
34
|
+
"@planningcenter/sweetest-alert": "^1.0.1",
|
|
34
35
|
"@planningcenter/tapestry": "^2.10.1",
|
|
35
36
|
"@planningcenter/url": "^3.2.0",
|
|
36
37
|
"react": "^18.3.0",
|
|
37
38
|
"react-dom": "^18.3.0",
|
|
38
39
|
"react-dropzone": "^14.0.0"
|
|
39
40
|
},
|
|
41
|
+
"prettier": {
|
|
42
|
+
"semi": false
|
|
43
|
+
},
|
|
40
44
|
"devDependencies": {
|
|
41
45
|
"@planningcenter/icons": "^15.29.1",
|
|
46
|
+
"@planningcenter/sweetest-alert": "^1.0.1",
|
|
42
47
|
"@planningcenter/tapestry": "^2.10.1",
|
|
43
48
|
"@planningcenter/url": "^3.2.0",
|
|
44
49
|
"@types/react": "^18.3.0",
|