Tailwind v4 (#5756)

* WIP

* Add tailwind migration script

* Change deprecated classes via migration script

* Manual fixes

* Restore color configuration with CSS variables

* Convert the rest of the config

* Fix dropdown ring opacity

* Remove migration script

* Fix stylelint errors

* NPM run format

* Fix shadow and rounded variant usage

* Add custom CSS to components layer

* Fix dark: and hover: conflict in settings_tab

* Fix funnel form background opacity

* Fix final bg-opacity

* Bring back cursor-pointer for buttons by default

* npm run format
This commit is contained in:
Uku Taht 2025-09-29 18:21:15 +03:00 committed by GitHub
parent 9ed79a831e
commit 6cdf8016e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
66 changed files with 259 additions and 237 deletions

View File

@ -0,0 +1,9 @@
{
"permissions": {
"allow": [
"Bash(iex:*)"
],
"deny": [],
"ask": []
}
}

View File

@ -0,0 +1,11 @@
{
"permissions": {
"allow": [
"Bash(grep:*)",
"Read(//Users/ukutaht/plausible/analytics/lib/**)",
"Bash(node:*)"
],
"deny": [],
"ask": []
}
}

View File

@ -3,7 +3,7 @@
"ignoreFiles": ["./node_modules/**/*.*"], "ignoreFiles": ["./node_modules/**/*.*"],
"rules": { "rules": {
"import-notation": "string", "import-notation": "string",
"at-rule-no-unknown": [true, { "ignoreAtRules": ["apply", "screen"] }], "at-rule-no-unknown": [true, { "ignoreAtRules": ["apply", "screen", "plugin", "source", "theme", "utility", "custom-variant"] }],
"at-rule-empty-line-before": [ "at-rule-empty-line-before": [
"always", "always",
{ "except": ["blockless-after-same-name-blockless"], "ignoreAtRules": ["apply"] } { "except": ["blockless-after-same-name-blockless"], "ignoreAtRules": ["apply"] }

View File

@ -1,15 +1,72 @@
@import 'tailwindcss/base'; @import 'tailwindcss' source(none);
@import 'flatpickr/dist/flatpickr.min.css'; @import 'flatpickr/dist/flatpickr.min.css' layer(components);
@import './modal.css'; @import './modal.css' layer(components);
@import './loader.css'; @import './loader.css' layer(components);
@import './tooltip.css'; @import './tooltip.css' layer(components);
@import './flatpickr-colors.css'; @import './flatpickr-colors.css' layer(components);
@import './chartjs.css'; @import './chartjs.css' layer(components);
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
[x-cloak] { @plugin "@tailwindcss/forms";
display: none;
@source "../css";
@source "../js";
@source "../../lib/plausible_web";
@source "../../extra/lib/plausible_web";
/* Tailwind v3 compatibility: restore v3 default border and ring styling */
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
button:not(:disabled),
[role='button']:not(:disabled) {
cursor: pointer;
}
}
@theme {
/* Color aliases from tailwind.config.js */
/* yellow: colors.amber - Map yellow to amber colors */
--color-yellow-50: var(--color-amber-50);
--color-yellow-100: var(--color-amber-100);
--color-yellow-200: var(--color-amber-200);
--color-yellow-300: var(--color-amber-300);
--color-yellow-400: var(--color-amber-400);
--color-yellow-500: var(--color-amber-500);
--color-yellow-600: var(--color-amber-600);
--color-yellow-700: var(--color-amber-700);
--color-yellow-800: var(--color-amber-800);
--color-yellow-900: var(--color-amber-900);
--color-yellow-950: var(--color-amber-950);
/* gray: colors.slate - Map gray to slate colors */
--color-gray-50: var(--color-slate-50);
--color-gray-100: var(--color-slate-100);
--color-gray-200: var(--color-slate-200);
--color-gray-300: var(--color-slate-300);
--color-gray-400: var(--color-slate-400);
--color-gray-500: var(--color-slate-500);
--color-gray-600: var(--color-slate-600);
--color-gray-700: var(--color-slate-700);
--color-gray-800: var(--color-slate-800);
--color-gray-900: var(--color-slate-900);
/* Custom gray shades from config (override some slate values) */
--color-gray-150: rgb(234 238 244);
--color-gray-825: rgb(37 47 63);
--color-gray-850: rgb(26 32 44);
--color-gray-950: rgb(13 18 30);
/* Set v3 default ring behavior */
--default-ring-width: 3px;
--default-ring-color: var(--color-blue-500);
} }
@media print { @media print {
@ -19,8 +76,22 @@
} }
} }
@utility container {
margin-inline: auto;
padding-inline: 1rem;
}
@custom-variant dark (&:where(.dark, .dark *));
@custom-variant phx-click-loading (.phx-click-loading&, .phx-click-loading &);
@custom-variant phx-submit-loading (.phx-submit-loading&, .phx-submit-loading &);
@custom-variant phx-change-loading (.phx-change-loading&, .phx-change-loading &);
[x-cloak] {
display: none;
}
.button { .button {
@apply inline-flex justify-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent rounded-md leading-5 transition hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500; @apply inline-flex justify-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent rounded-md leading-5 transition hover:bg-indigo-700 focus:outline-hidden focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500;
} }
.button[disabled] { .button[disabled] {
@ -58,7 +129,7 @@ blockquote {
@apply px-4 py-2 my-4 border-l-4 border-gray-500; @apply px-4 py-2 my-4 border-l-4 border-gray-500;
} }
@screen xl { @media (width >= 1280px) {
.container { .container {
max-width: 70rem; max-width: 70rem;
} }
@ -68,7 +139,7 @@ blockquote {
height: 920px; height: 920px;
} }
@screen md { @media (width >= 768px) {
.pricing-table { .pricing-table {
height: auto; height: auto;
} }

View File

@ -1,10 +1,8 @@
@import 'tailwindcss/base'; @import 'tailwindcss' source(none);
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
/* /*
* Put your component styling within the Tailwind utilities layer. * Put your component styling within the Tailwind utilities layer.
* See the https://hexdocs.pm/phoenix_storybook/sandboxing.html guide for more info. * See the https://hexdocs.pm/phoenix_storybook/sandboxing.html guide for more info.
*/ */
@layer utilities { @layer utilities {

View File

@ -221,7 +221,7 @@ export default function PlausibleCombobox({
}, [isEmpty, singleOption, autoFocus]) }, [isEmpty, singleOption, autoFocus])
const searchBoxClass = const searchBoxClass =
'border-none py-1 px-0 w-full inline-block rounded-md focus:outline-none focus:ring-0 text-sm' 'border-none py-1 px-0 w-full inline-block rounded-md focus:outline-hidden focus:ring-0 text-sm'
const containerClass = classNames('relative w-full', { const containerClass = classNames('relative w-full', {
[className]: !!className, [className]: !!className,
@ -264,7 +264,7 @@ export default function PlausibleCombobox({
return ( return (
<div <div
key={value.value} key={value.value}
className="bg-indigo-100 dark:bg-indigo-600 flex justify-between w-full rounded-sm px-2 py-0.5 m-0.5 text-sm" className="bg-indigo-100 dark:bg-indigo-600 flex justify-between w-full rounded-xs px-2 py-0.5 m-0.5 text-sm"
> >
<span className="break-all">{value.label}</span> <span className="break-all">{value.label}</span>
<span <span
@ -340,7 +340,7 @@ export default function PlausibleCombobox({
} }
const defaultBoxClass = const defaultBoxClass =
'pl-2 pr-8 py-1 w-full dark:bg-gray-900 dark:text-gray-300 rounded-md shadow-sm border border-gray-300 dark:border-gray-700 focus-within:border-indigo-500 focus-within:ring-1 focus-within:ring-indigo-500' 'pl-2 pr-8 py-1 w-full dark:bg-gray-900 dark:text-gray-300 rounded-md shadow-xs border border-gray-300 dark:border-gray-700 focus-within:border-indigo-500 focus-within:ring-1 focus-within:ring-indigo-500'
const finalBoxClass = classNames(boxClass || defaultBoxClass, { const finalBoxClass = classNames(boxClass || defaultBoxClass, {
'border-indigo-500 ring-1 ring-indigo-500': isOpen 'border-indigo-500 ring-1 ring-indigo-500': isOpen
}) })
@ -365,7 +365,7 @@ export default function PlausibleCombobox({
> >
<ul <ul
ref={listRef} ref={listRef}
className="z-50 absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm dark:bg-gray-900" className="z-50 absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1/5 ring-black focus:outline-hidden sm:text-sm dark:bg-gray-900"
> >
{renderDropDownContent()} {renderDropDownContent()}
</ul> </ul>

View File

@ -28,7 +28,7 @@ export default function FilterOperatorSelector(props) {
<BlurMenuButtonOnEscape targetRef={buttonRef} /> <BlurMenuButtonOnEscape targetRef={buttonRef} />
<Popover.Button <Popover.Button
ref={buttonRef} ref={buttonRef}
className="relative flex justify-between items-center w-full rounded-md border border-gray-300 dark:border-gray-500 shadow-sm px-4 py-2 bg-white dark:bg-gray-800 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-850 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 dark:focus:ring-offset-gray-900 focus:ring-indigo-500 text-left" className="relative flex justify-between items-center w-full rounded-md border border-gray-300 dark:border-gray-500 shadow-xs px-4 py-2 bg-white dark:bg-gray-800 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-850 focus:outline-hidden focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 dark:focus:ring-offset-gray-900 focus:ring-indigo-500 text-left"
> >
{FILTER_OPERATIONS_DISPLAY_NAMES[props.selectedType]} {FILTER_OPERATIONS_DISPLAY_NAMES[props.selectedType]}
<ChevronDownIcon <ChevronDownIcon

View File

@ -26,7 +26,7 @@ const transition = {
const panel = { const panel = {
classNames: { classNames: {
roundedSheet: roundedSheet:
'focus:outline-none rounded-md shadow-lg bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 font-medium text-gray-800 dark:text-gray-200' 'focus:outline-hidden rounded-md shadow-lg bg-white dark:bg-gray-800 ring-1 ring-black/5 font-medium text-gray-800 dark:text-gray-200'
} }
} }
@ -34,7 +34,7 @@ const toggleButton = {
classNames: { classNames: {
rounded: 'flex items-center rounded text-sm leading-tight h-9', rounded: 'flex items-center rounded text-sm leading-tight h-9',
shadow: shadow:
'bg-white dark:bg-gray-800 shadow text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-900', 'bg-white dark:bg-gray-800 shadow-sm text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-900',
ghost: ghost:
'text-gray-700 dark:text-gray-100 hover:bg-gray-200 dark:hover:bg-gray-900', 'text-gray-700 dark:text-gray-100 hover:bg-gray-200 dark:hover:bg-gray-900',
truncatedText: 'truncate block font-medium', truncatedText: 'truncate block font-medium',

View File

@ -78,7 +78,7 @@ export const DropdownTabButton = ({
<> <>
<BlurMenuButtonOnEscape targetRef={dropdownButtonRef} /> <BlurMenuButtonOnEscape targetRef={dropdownButtonRef} />
<Popover.Button <Popover.Button
className="inline-flex justify-between rounded-sm" className="inline-flex justify-between rounded-xs"
ref={dropdownButtonRef} ref={dropdownButtonRef}
> >
<TabButtonText active={active}>{children}</TabButtonText> <TabButtonText active={active}>{children}</TabButtonText>

View File

@ -17,7 +17,7 @@ function DashboardStats({
updateImportedDataInView?: (v: boolean) => void updateImportedDataInView?: (v: boolean) => void
}) { }) {
const statsBoxClass = const statsBoxClass =
'relative min-h-[436px] w-full mt-5 p-4 flex flex-col bg-white dark:bg-gray-825 shadow rounded-md md:min-h-initial md:h-27.25rem md:w-[calc(50%-10px)] md:ml-[10px] md:mr-[10px] first:ml-0 last:mr-0' 'relative min-h-[436px] w-full mt-5 p-4 flex flex-col bg-white dark:bg-gray-825 shadow-sm rounded-md md:min-h-initial md:h-27.25rem md:w-[calc(50%-10px)] md:ml-[10px] md:mr-[10px] first:ml-0 last:mr-0'
return ( return (
<> <>

View File

@ -265,7 +265,7 @@ const SeeMoreMenu = ({
aria-hidden="true" aria-hidden="true"
className="absolute flex justify-end left-0 right-0 bottom-0 translate-y-1/4 pr-[3px]" className="absolute flex justify-end left-0 right-0 bottom-0 translate-y-1/4 pr-[3px]"
> >
<div className="text-[10px] leading-[10px] min-w-[10px] font-medium shadow px-[3px] py-[1px] flex items-center rounded-sm bg-gray-100 dark:bg-gray-850"> <div className="text-[10px] leading-[10px] min-w-[10px] font-medium shadow-sm px-[3px] py-[1px] flex items-center rounded-xs bg-gray-100 dark:bg-gray-850">
+{filtersInMenuCount} +{filtersInMenuCount}
</div> </div>
</div> </div>

View File

@ -59,7 +59,7 @@ export const SegmentMenu = () => {
} }
return ( return (
<div className="flex shadow"> <div className="flex shadow-sm">
<AppNavigationLink <AppNavigationLink
className={classNames( className={classNames(
popover.toggleButton.classNames.rounded, popover.toggleButton.classNames.rounded,

View File

@ -238,7 +238,7 @@ const SegmentNameInput = ({
onChange={(e) => onChange(e.target.value)} onChange={(e) => onChange(e.target.value)}
placeholder={namePlaceholder} placeholder={namePlaceholder}
id="name" id="name"
className="block mt-2 p-2 w-full dark:bg-gray-900 dark:text-gray-300 rounded-md shadow-sm border border-gray-300 dark:border-gray-700 focus-within:border-indigo-500 focus-within:ring-1 focus-within:ring-indigo-500" className="block mt-2 p-2 w-full dark:bg-gray-900 dark:text-gray-300 rounded-md shadow-xs border border-gray-300 dark:border-gray-700 focus-within:border-indigo-500 focus-within:ring-1 focus-within:ring-indigo-500"
/> />
</> </>
) )

View File

@ -347,7 +347,7 @@ export default function Behaviours({ importedDataInView }) {
return ( return (
<div className="items-start justify-between block w-full mt-6 md:flex relative"> <div className="items-start justify-between block w-full mt-6 md:flex relative">
<div className="w-full p-4 bg-white rounded-md shadow dark:bg-gray-825"> <div className="w-full p-4 bg-white rounded-md shadow-sm dark:bg-gray-825">
<div className="flex justify-between w-full"> <div className="flex justify-between w-full">
<div className="flex gap-x-1"> <div className="flex gap-x-1">
<h3 className="font-bold dark:text-gray-100"> <h3 className="font-bold dark:text-gray-100">

View File

@ -126,7 +126,7 @@ export default function TopStats({
const [statDisplayName, statExtraName] = stat.name.split(/(\(.+\))/g) const [statDisplayName, statExtraName] = stat.name.split(/(\(.+\))/g)
const statDisplayNameClass = classNames( const statDisplayNameClass = classNames(
'text-xs font-bold tracking-wide text-gray-500 uppercase dark:text-gray-400 whitespace-nowrap flex w-content border-b', 'text-xs font-bold tracking-wide text-gray-500 uppercase dark:text-gray-400 whitespace-nowrap flex w-fit border-b',
{ {
'text-indigo-700 dark:text-indigo-500 border-indigo-700 dark:border-indigo-500': 'text-indigo-700 dark:text-indigo-500 border-indigo-700 dark:border-indigo-500':
isSelected, isSelected,

View File

@ -81,7 +81,7 @@ class Modal extends React.Component {
<button className="modal__close"></button> <button className="modal__close"></button>
<div <div
ref={this.node} ref={this.node}
className="modal__container dark:bg-gray-800 focus:outline-none" className="modal__container dark:bg-gray-800 focus:outline-hidden"
style={this.getStyle()} style={this.getStyle()}
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
tabIndex={0} tabIndex={0}

View File

@ -201,7 +201,7 @@ export default function ListReport<
<div style={{ height: ROW_HEIGHT }}>{renderReportHeader()}</div> <div style={{ height: ROW_HEIGHT }}>{renderReportHeader()}</div>
<div style={{ minHeight: DATA_CONTAINER_HEIGHT }}> <div style={{ minHeight: DATA_CONTAINER_HEIGHT }}>
<FlipMove className="flex-grow"> <FlipMove className="grow">
{state.list.slice(0, MAX_ITEMS).map(renderRow)} {state.list.slice(0, MAX_ITEMS).map(renderRow)}
</FlipMove> </FlipMove>
</div> </div>
@ -237,7 +237,7 @@ export default function ListReport<
return ( return (
<div className="pt-3 w-full text-xs font-bold tracking-wide text-gray-500 flex items-center dark:text-gray-400"> <div className="pt-3 w-full text-xs font-bold tracking-wide text-gray-500 flex items-center dark:text-gray-400">
<span className="flex-grow truncate">{keyLabel}</span> <span className="grow truncate">{keyLabel}</span>
{metricLabels} {metricLabels}
</div> </div>
) )
@ -262,12 +262,12 @@ export default function ListReport<
const metricToPlot = metrics.find((metric) => metric.meta.plot)?.key const metricToPlot = metrics.find((metric) => metric.meta.plot)?.key
return ( return (
<div className="flex-grow w-full overflow-hidden"> <div className="grow w-full overflow-hidden">
<Bar <Bar
maxWidthDeduction={undefined} maxWidthDeduction={undefined}
count={listItem[metricToPlot]} count={listItem[metricToPlot]}
all={state.list} all={state.list}
bg={`${lightBackground} dark:bg-gray-500 dark:bg-opacity-15`} bg={`${lightBackground} dark:bg-gray-500/15`}
plot={metricToPlot} plot={metricToPlot}
> >
<div className="flex justify-start px-2 py-1.5 group text-sm dark:text-gray-300 relative z-9 break-all w-full"> <div className="flex justify-start px-2 py-1.5 group text-sm dark:text-gray-300 relative z-9 break-all w-full">

View File

@ -69,7 +69,7 @@ export default function Referrers({ source }) {
} }
return ( return (
<div className="flex flex-col flex-grow"> <div className="flex flex-col grow">
<div className="flex gap-x-1"> <div className="flex gap-x-1">
<h3 className="font-bold dark:text-gray-100">Top Referrers</h3> <h3 className="font-bold dark:text-gray-100">Top Referrers</h3>
<ImportedQueryUnsupportedWarning <ImportedQueryUnsupportedWarning

View File

@ -131,7 +131,7 @@ export function SearchTerms() {
<Bar <Bar
count={term.visitors} count={term.visitors}
all={searchTerms} all={searchTerms}
bg="bg-blue-50 dark:bg-gray-500 dark:bg-opacity-15" bg="bg-blue-50 dark:bg-gray-500/15"
maxWidthDeduction="4rem" maxWidthDeduction="4rem"
> >
<span className="flex px-2 py-1.5 dark:text-gray-300 z-9 relative break-all"> <span className="flex px-2 py-1.5 dark:text-gray-300 z-9 relative break-all">
@ -188,7 +188,7 @@ export function SearchTerms() {
return ( return (
<div className="flex flex-col h-full"> <div className="flex flex-col h-full">
<h3 className="font-bold dark:text-gray-100">Search Terms</h3> <h3 className="font-bold dark:text-gray-100">Search Terms</h3>
<div className="relative flex-grow"> <div className="relative grow">
{loading && ( {loading && (
<div className="absolute inset-0 flex justify-center items-center"> <div className="absolute inset-0 flex justify-center items-center">
<div className="loading"> <div className="loading">
@ -196,7 +196,7 @@ export function SearchTerms() {
</div> </div>
</div> </div>
)} )}
<FadeIn show={!loading} className="flex-grow"> <FadeIn show={!loading} className="grow">
<LazyLoader onVisible={onVisible}> <LazyLoader onVisible={onVisible}>
{searchTerms && searchTerms.length > 0 && renderList()} {searchTerms && searchTerms.length > 0 && renderList()}
{searchTerms && searchTerms.length === 0 && renderNoDataYet()} {searchTerms && searchTerms.length === 0 && renderNoDataYet()}

View File

@ -99,7 +99,7 @@ function TooltipMessage({
ref={setPopperElement} ref={setPopperElement}
style={popperStyle} style={popperStyle}
{...popperAttributes} {...popperAttributes}
className="z-50 p-2 rounded text-sm text-gray-100 font-bold popper-tooltip" className="z-50 p-2 rounded-sm text-sm text-gray-100 font-bold popper-tooltip"
role="tooltip" role="tooltip"
> >
{children} {children}

View File

@ -14,8 +14,7 @@
"@jsonurl/jsonurl": "^1.1.7", "@jsonurl/jsonurl": "^1.1.7",
"@juggle/resize-observer": "^3.3.1", "@juggle/resize-observer": "^3.3.1",
"@popperjs/core": "^2.11.6", "@popperjs/core": "^2.11.6",
"@tailwindcss/aspect-ratio": "^0.4.2", "@tailwindcss/forms": "^0.5.10",
"@tailwindcss/forms": "^0.5.6",
"@tailwindcss/typography": "^0.4.1", "@tailwindcss/typography": "^0.4.1",
"@tanstack/react-query": "^5.51.1", "@tanstack/react-query": "^5.51.1",
"abortcontroller-polyfill": "^1.7.3", "abortcontroller-polyfill": "^1.7.3",
@ -1630,21 +1629,16 @@
"@sinonjs/commons": "^3.0.0" "@sinonjs/commons": "^3.0.0"
} }
}, },
"node_modules/@tailwindcss/aspect-ratio": {
"version": "0.4.2",
"license": "MIT",
"peerDependencies": {
"tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1"
}
},
"node_modules/@tailwindcss/forms": { "node_modules/@tailwindcss/forms": {
"version": "0.5.6", "version": "0.5.10",
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.10.tgz",
"integrity": "sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"mini-svg-data-uri": "^1.2.3" "mini-svg-data-uri": "^1.2.3"
}, },
"peerDependencies": { "peerDependencies": {
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1"
} }
}, },
"node_modules/@tailwindcss/typography": { "node_modules/@tailwindcss/typography": {
@ -8097,6 +8091,8 @@
}, },
"node_modules/mini-svg-data-uri": { "node_modules/mini-svg-data-uri": {
"version": "1.4.4", "version": "1.4.4",
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
"integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
"license": "MIT", "license": "MIT",
"bin": { "bin": {
"mini-svg-data-uri": "cli.js" "mini-svg-data-uri": "cli.js"

View File

@ -4,7 +4,7 @@
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"scripts": { "scripts": {
"test": "TZ=UTC jest", "test": "TZ=UTC jest",
"format": "prettier --write", "format": "prettier --write \"**/*.{js,css,ts,tsx}\"",
"check-format": "prettier --check \"**/*.{js,css,ts,tsx}\"", "check-format": "prettier --check \"**/*.{js,css,ts,tsx}\"",
"eslint": "eslint js/**", "eslint": "eslint js/**",
"stylelint": "stylelint css/**", "stylelint": "stylelint css/**",
@ -18,8 +18,7 @@
"@jsonurl/jsonurl": "^1.1.7", "@jsonurl/jsonurl": "^1.1.7",
"@juggle/resize-observer": "^3.3.1", "@juggle/resize-observer": "^3.3.1",
"@popperjs/core": "^2.11.6", "@popperjs/core": "^2.11.6",
"@tailwindcss/aspect-ratio": "^0.4.2", "@tailwindcss/forms": "^0.5.10",
"@tailwindcss/forms": "^0.5.6",
"@tailwindcss/typography": "^0.4.1", "@tailwindcss/typography": "^0.4.1",
"@tanstack/react-query": "^5.51.1", "@tanstack/react-query": "^5.51.1",
"abortcontroller-polyfill": "^1.7.3", "abortcontroller-polyfill": "^1.7.3",

View File

@ -1,60 +0,0 @@
const colors = require('tailwindcss/colors')
const plugin = require('tailwindcss/plugin')
module.exports = {
content: [
"./js/**/*.{js,ts,tsx}",
"../lib/*_web.ex",
"../lib/*_web/**/*.*ex",
"../extra/**/*.*ex",
],
safelist: [
// PlausibleWeb.StatsView.stats_container_class/1 uses this class
// it's not used anywhere else in the templates or scripts
"max-w-screen-xl"
],
darkMode: 'class',
theme: {
container: {
center: true,
padding: '1rem',
},
extend: {
colors: {
yellow: colors.amber, // We started using `yellow` in v2 but it was renamed to `amber` in v3 https://tailwindcss.com/docs/upgrade-guide#removed-color-aliases
gray: colors.slate,
'gray-150': 'rgb(234, 238, 244)',
'gray-950': 'rgb(13, 18, 30)',
'gray-850': 'rgb(26, 32, 44)',
'gray-825': 'rgb(37, 47, 63)'
},
spacing: {
'44': '11rem'
},
width: {
'content': 'fit-content'
},
opacity: {
'15': '0.15',
},
zIndex: {
'9': 9,
},
maxWidth: {
'2xs': '15rem',
'3xs': '12rem',
},
transitionProperty: {
'padding': 'padding',
}
},
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/aspect-ratio'),
plugin(({ addVariant }) => addVariant("phx-click-loading", [".phx-click-loading&", ".phx-click-loading &"])),
plugin(({ addVariant }) => addVariant("phx-submit-loading", [".phx-submit-loading&", ".phx-submit-loading &"])),
plugin(({ addVariant }) => addVariant("phx-change-loading", [".phx-change-loading&", ".phx-change-loading &"])),
plugin(({ addVariant }) => addVariant("ui-disabled", ["&[data-ui-state~=\"disabled\"]", ":where([data-ui-state~=\"disabled\"]) &"])),
]
}

View File

@ -26,22 +26,20 @@ config :esbuild,
] ]
config :tailwind, config :tailwind,
version: "3.4.7", version: "4.1.12",
default: [ default: [
args: ~w( args: ~w(
--config=tailwind.config.js --input=assets/css/app.css
--input=css/app.css --output=priv/static/css/app.css
--output=../priv/static/css/app.css
), ),
cd: Path.expand("../assets", __DIR__) cd: Path.expand("..", __DIR__)
], ],
storybook: [ storybook: [
args: ~w( args: ~w(
--config=tailwind.config.js --input=assets/css/storybook.css
--input=css/storybook.css --output=priv/static/css/storybook.css
--output=../priv/static/css/storybook.css
), ),
cd: Path.expand("../assets", __DIR__) cd: Path.expand("..", __DIR__)
] ]
config :ua_inspector, config :ua_inspector,

View File

@ -52,7 +52,7 @@ defmodule PlausibleWeb.CustomerSupport.Components.Layout do
id="help" id="help"
x-show="openHelp" x-show="openHelp"
x-cloak x-cloak
class="p-16 fixed top-0 left-0 w-full h-full bg-gray-800 text-gray-300 bg-opacity-95 z-50 flex items-center justify-center" class="p-16 fixed top-0 left-0 w-full h-full bg-gray-800/95 text-gray-300 z-50 flex items-center justify-center"
> >
<div @click.away="openHelp = false" @click="openHelp = false"> <div @click.away="openHelp = false" @click="openHelp = false">
Prefix your searches with: <br /><br /> Prefix your searches with: <br /><br />

View File

@ -48,7 +48,7 @@ defmodule PlausibleWeb.Live.FunnelSettings.Form do
def render(assigns) do def render(assigns) do
~H""" ~H"""
<div <div
class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity z-50" class="fixed inset-0 bg-gray-500/75 transition-opacity z-50"
phx-window-keydown="cancel-add-funnel" phx-window-keydown="cancel-add-funnel"
phx-key="Escape" phx-key="Escape"
> >

View File

@ -288,14 +288,14 @@ defmodule PlausibleWeb.Live.Verification do
name="custom_url" name="custom_url"
id="custom_url" id="custom_url"
required required
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:text-white" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-xs focus:outline-hidden focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:text-white"
placeholder={"https://#{@domain}"} placeholder={"https://#{@domain}"}
value={"https://#{@domain}"} value={"https://#{@domain}"}
/> />
</div> </div>
<button <button
type="submit" type="submit"
class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:bg-indigo-500 dark:hover:bg-indigo-600" class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-xs text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-hidden focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:bg-indigo-500 dark:hover:bg-indigo-600"
> >
Verify Installation Verify Installation
</button> </button>

View File

@ -209,7 +209,7 @@ defmodule PlausibleWeb.Components.Billing do
~H""" ~H"""
<div <div
id="monthly-quota-box" id="monthly-quota-box"
class="w-full flex-1 h-32 px-2 py-4 text-center bg-gray-100 rounded dark:bg-gray-900 w-max-md" class="w-full flex-1 h-32 px-2 py-4 text-center bg-gray-100 rounded-sm dark:bg-gray-900 w-max-md"
> >
<h4 class="font-black dark:text-gray-100">Monthly quota</h4> <h4 class="font-black dark:text-gray-100">Monthly quota</h4>
<div class="py-2 text-xl font-medium dark:text-gray-100"> <div class="py-2 text-xl font-medium dark:text-gray-100">

View File

@ -46,7 +46,7 @@ defmodule PlausibleWeb.Components.Billing.PageviewSlider do
phx-change="slide" phx-change="slide"
id="slider" id="slider"
name="slider" name="slider"
class="shadow dark:bg-gray-600 dark:border-none" class="shadow-sm dark:bg-gray-600 dark:border-none"
type="range" type="range"
min="0" min="0"
max={length(@available_volumes)} max={length(@available_volumes)}

View File

@ -22,7 +22,7 @@ defmodule PlausibleWeb.Components.FirstDashboardLaunchBanner do
<div <div
x-cloak x-cloak
x-data={x_data(@site)} x-data={x_data(@site)}
class="w-full px-4 text-sm font-bold text-center text-blue-900 bg-blue-200 rounded transition" class="w-full px-4 text-sm font-bold text-center text-blue-900 bg-blue-200 rounded-sm transition"
style="top: 91px" style="top: 91px"
role="alert" role="alert"
x-bind:class="! show ? 'hidden' : ''" x-bind:class="! show ? 'hidden' : ''"

View File

@ -196,7 +196,7 @@ defmodule PlausibleWeb.Components.Generic do
<Heroicons.x_mark class="h-4 w-4 hover:stroke-2" /> <Heroicons.x_mark class="h-4 w-4 hover:stroke-2" />
</button> </button>
<div class="flex gap-x-3"> <div class="flex gap-x-3">
<div :if={@title} class="flex-shrink-0"> <div :if={@title} class="shrink-0">
<svg <svg
class={"h-5 w-5 #{@theme.icon}"} class={"h-5 w-5 #{@theme.icon}"}
viewBox="0 0 20 20" viewBox="0 0 20 20"
@ -296,7 +296,7 @@ defmodule PlausibleWeb.Components.Generic do
x-on:click.outside="close($refs.button)" x-on:click.outside="close($refs.button)"
style="display: none;" style="display: none;"
class={[ class={[
"origin-top-right absolute z-50 right-0 mt-2 p-1.5 w-max rounded-md shadow-lg overflow-hidden bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 focus:outline-none", "origin-top-right absolute z-50 right-0 mt-2 p-1.5 w-max rounded-md shadow-lg overflow-hidden bg-white dark:bg-gray-800 ring-1 ring-black/5 focus:outline-none",
@menu_class @menu_class
]} ]}
> >
@ -450,12 +450,12 @@ defmodule PlausibleWeb.Components.Generic do
{@rest} {@rest}
> >
<span <span
class="relative inline-flex h-6 w-11 flex-shrink-0 rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2" class="relative inline-flex h-6 w-11 shrink-0 rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-hidden focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2"
x-bind:class={"#{@js_active_var} ? 'bg-indigo-600' : 'dark:bg-gray-700 bg-gray-200'"} x-bind:class={"#{@js_active_var} ? 'bg-indigo-600' : 'dark:bg-gray-700 bg-gray-200'"}
> >
<span <span
aria-hidden="true" aria-hidden="true"
class="pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out" class="pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow-sm ring-0 transition duration-200 ease-in-out"
x-bind:class={"#{@js_active_var} ? 'dark:bg-gray-800 translate-x-5' : 'dark:bg-gray-800 translate-x-0'"} x-bind:class={"#{@js_active_var} ? 'dark:bg-gray-800 translate-x-5' : 'dark:bg-gray-800 translate-x-0'"}
/> />
</span> </span>
@ -484,7 +484,7 @@ defmodule PlausibleWeb.Components.Generic do
def tile(assigns) do def tile(assigns) do
~H""" ~H"""
<div class="shadow bg-white dark:bg-gray-800 rounded-md mb-6"> <div class="shadow-sm bg-white dark:bg-gray-800 rounded-md mb-6">
<header class="relative py-4 px-6"> <header class="relative py-4 px-6">
<.title> <.title>
{render_slot(@title)} {render_slot(@title)}
@ -580,7 +580,7 @@ defmodule PlausibleWeb.Components.Generic do
x-transition:leave-start="opacity-100" x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0" x-transition:leave-end="opacity-0"
> >
<div class="bg-gray-900 text-white rounded px-2.5 py-1.5 text-xs font-medium"> <div class="bg-gray-900 text-white rounded-sm px-2.5 py-1.5 text-xs font-medium">
{render_slot(@tooltip_content)} {render_slot(@tooltip_content)}
</div> </div>
</div> </div>
@ -918,7 +918,7 @@ defmodule PlausibleWeb.Components.Generic do
def filter_bar(assigns) do def filter_bar(assigns) do
~H""" ~H"""
<div class="mb-6 flex items-center justify-between" x-data> <div class="mb-6 flex items-center justify-between" x-data>
<div :if={@filtering_enabled?} class="relative rounded-md shadow-sm flex"> <div :if={@filtering_enabled?} class="relative rounded-md shadow-xs flex">
<form id="filter-form" phx-change="filter" phx-submit="filter" class="flex items-center"> <form id="filter-form" phx-change="filter" phx-submit="filter" class="flex items-center">
<div class="text-gray-800 inline-flex items-center"> <div class="text-gray-800 inline-flex items-center">
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3"> <div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
@ -928,7 +928,7 @@ defmodule PlausibleWeb.Components.Generic do
type="text" type="text"
name="filter-text" name="filter-text"
id="filter-text" id="filter-text"
class="w-36 sm:w-full pl-8 text-sm shadow-sm dark:bg-gray-900 dark:text-gray-300 focus:ring-indigo-500 focus:border-indigo-500 block border-gray-300 dark:border-gray-500 rounded-md dark:bg-gray-800" class="w-36 sm:w-full pl-8 text-sm shadow-xs dark:bg-gray-900 dark:text-gray-300 focus:ring-indigo-500 focus:border-indigo-500 block border-gray-300 dark:border-gray-500 rounded-md dark:bg-gray-800"
placeholder="Press / to search" placeholder="Press / to search"
x-ref="filter_text" x-ref="filter_text"
phx-debounce={200} phx-debounce={200}

View File

@ -12,7 +12,7 @@ defmodule PlausibleWeb.Components.Google do
<.unstyled_link <.unstyled_link
id={@id} id={@id}
href={@to} href={@to}
class="inline-flex pr-4 items-center border border-gray-100 shadow rounded-md focus:outline-none focus:ring-1 focus:ring-offset-1 focus:ring-gray-200 mt-8 hover:bg-gray-50 dark:hover:bg-gray-700" class="inline-flex pr-4 items-center border border-gray-100 shadow-sm rounded-md focus:outline-hidden focus:ring-1 focus:ring-offset-1 focus:ring-gray-200 mt-8 hover:bg-gray-50 dark:hover:bg-gray-700"
> >
<.logo /> <.logo />
<span <span

View File

@ -128,7 +128,7 @@ defmodule PlausibleWeb.Components.Layout do
class={[ class={[
"text-sm flex items-center px-2 py-2 leading-5 font-medium rounded-md outline-none focus:outline-none transition ease-in-out duration-150", "text-sm flex items-center px-2 py-2 leading-5 font-medium rounded-md outline-none focus:outline-none transition ease-in-out duration-150",
@current_tab? && @current_tab? &&
"text-gray-900 dark:text-gray-100 bg-gray-150 font-semibold dark:bg-gray-700/50 hover:text-gray-900 focus:bg-gray-200 dark:focus:bg-gray-800", "text-gray-900 dark:text-gray-100 bg-gray-150 font-semibold dark:bg-gray-700/50 hover:text-gray-900 dark:hover:text-gray-100 focus:bg-gray-200 dark:focus:bg-gray-800",
@value && not @current_tab? && @value && not @current_tab? &&
"text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-800 focus:text-gray-900 focus:bg-gray-50 dark:focus:text-gray-100 dark:focus:bg-gray-800", "text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-800 focus:text-gray-900 focus:bg-gray-50 dark:focus:text-gray-100 dark:focus:bg-gray-800",
!@value && "text-gray-600 dark:text-gray-300" !@value && "text-gray-600 dark:text-gray-300"

View File

@ -112,7 +112,7 @@ defmodule PlausibleWeb.Components.TwoFactor do
x-transition:leave="transition ease-in duration-200" x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100" x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0" x-transition:leave-end="opacity-0"
class="fixed inset-0 bg-gray-500 dark:bg-gray-800 bg-opacity-75 dark:bg-opacity-75 transition-opacity" class="fixed inset-0 bg-gray-500/75 dark:bg-gray-800/75 transition-opacity"
aria-hidden="true" aria-hidden="true"
x-on:click={"#{@state_param} = false"} x-on:click={"#{@state_param} = false"}
> >
@ -138,14 +138,14 @@ defmodule PlausibleWeb.Components.TwoFactor do
<a <a
href="#" href="#"
x-on:click.prevent={"#{@state_param} = false"} x-on:click.prevent={"#{@state_param} = false"}
class="bg-white dark:bg-gray-800 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 focus:outline-none" class="bg-white dark:bg-gray-800 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 focus:outline-hidden"
> >
<span class="sr-only">Close</span> <span class="sr-only">Close</span>
<Heroicons.x_mark class="h-6 w-6" /> <Heroicons.x_mark class="h-6 w-6" />
</a> </a>
</div> </div>
<div class="sm:flex sm:items-start"> <div class="sm:flex sm:items-start">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-green-100 sm:mx-0 sm:h-10 sm:w-10"> <div class="mx-auto shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-green-100 sm:mx-0 sm:h-10 sm:w-10">
{render_slot(@icon)} {render_slot(@icon)}
</div> </div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left text-gray-900 dark:text-gray-100"> <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left text-gray-900 dark:text-gray-100">

View File

@ -324,7 +324,7 @@ defmodule PlausibleWeb.Live.ChoosePlan do
<div class="lg:flex-1 lg:order-3 lg:justify-end flex"> <div class="lg:flex-1 lg:order-3 lg:justify-end flex">
<div class="relative"> <div class="relative">
<.two_months_free /> <.two_months_free />
<fieldset class="grid grid-cols-2 gap-x-1 rounded-full bg-white dark:bg-gray-700 p-1 text-center text-sm font-semibold leading-5 shadow dark:ring-gray-600"> <fieldset class="grid grid-cols-2 gap-x-1 rounded-full bg-white dark:bg-gray-700 p-1 text-center text-sm font-semibold leading-5 shadow-sm dark:ring-gray-600">
<label <label
class={"cursor-pointer rounded-full px-2.5 py-1 text-gray-900 dark:text-white #{if @selected_interval == :monthly, do: "bg-indigo-600 text-white"}"} class={"cursor-pointer rounded-full px-2.5 py-1 text-gray-900 dark:text-white #{if @selected_interval == :monthly, do: "bg-indigo-600 text-white"}"}
phx-click="set_interval" phx-click="set_interval"

View File

@ -1,7 +1,7 @@
defmodule PlausibleWeb.Live.Components.ComboBox do defmodule PlausibleWeb.Live.Components.ComboBox do
@moduledoc """ @moduledoc """
Phoenix LiveComponent for a combobox UI element with search and selection Phoenix LiveComponent for a combobox UI element with search and selection
functionality. functionality.
The component allows users to select an option from a list of options, The component allows users to select an option from a list of options,
which can be searched by typing in the input field. which can be searched by typing in the input field.
@ -90,7 +90,7 @@ defmodule PlausibleWeb.Live.Components.ComboBox do
<div class="relative w-full"> <div class="relative w-full">
<div <div
@click.away="close" @click.away="close"
class="pl-2 pr-8 py-1 w-full dark:bg-gray-900 dark:text-gray-300 rounded-md shadow-sm border border-gray-300 dark:border-gray-700 focus-within:border-indigo-500 focus-within:ring-1 focus-within:ring-indigo-500" class="pl-2 pr-8 py-1 w-full dark:bg-gray-900 dark:text-gray-300 rounded-md shadow-xs border border-gray-300 dark:border-gray-700 focus-within:border-indigo-500 focus-within:ring-1 focus-within:ring-indigo-500"
> >
<input <input
type="text" type="text"
@ -105,7 +105,7 @@ defmodule PlausibleWeb.Live.Components.ComboBox do
phx-target={@myself} phx-target={@myself}
phx-debounce={200} phx-debounce={200}
value={@display_value} value={@display_value}
class="text-sm [&.phx-change-loading+svg.spinner]:block border-none py-1.5 px-1.5 w-full inline-block rounded-md focus:outline-none focus:ring-0" class="text-sm [&.phx-change-loading+svg.spinner]:block border-none py-1.5 px-1.5 w-full inline-block rounded-md focus:outline-hidden focus:ring-0"
style="background-color: inherit;" style="background-color: inherit;"
required={@required} required={@required}
/> />
@ -180,7 +180,7 @@ defmodule PlausibleWeb.Live.Components.ComboBox do
id={"dropdown-#{@ref}"} id={"dropdown-#{@ref}"}
x-show="isOpen" x-show="isOpen"
x-ref="suggestions" x-ref="suggestions"
class="text-sm w-full dropdown z-50 absolute mt-1 max-h-60 overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:bg-gray-900" class="text-sm w-full dropdown z-50 absolute mt-1 max-h-60 overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1/5 ring-black focus:outline-hidden dark:bg-gray-900"
style="display: none;" style="display: none;"
> >
<.option <.option

View File

@ -110,7 +110,7 @@ defmodule PlausibleWeb.Live.Components.Form do
checked={@checked} checked={@checked}
id={@id} id={@id}
name={@name} name={@name}
class="block h-5 w-5 rounded dark:bg-gray-700 border-gray-300 text-indigo-600 focus:ring-indigo-600" class="block h-5 w-5 rounded-sm dark:bg-gray-700 border-gray-300 text-indigo-600 focus:ring-indigo-600"
{@rest} {@rest}
/> />
{@label} {@label}
@ -441,7 +441,7 @@ defmodule PlausibleWeb.Live.Components.Form do
type="select" type="select"
options={@options} options={@options}
onchange={"if (event.target.value) { location.href = '#{@href_base}' + event.target.value }"} onchange={"if (event.target.value) { location.href = '#{@href_base}' + event.target.value }"}
class="dark:bg-gray-800 mt-1 block w-full pl-3.5 pr-10 py-2.5 text-base border-gray-300 dark:border-gray-500 outline-none focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 rounded-md dark:text-gray-100" class="dark:bg-gray-800 mt-1 block w-full pl-3.5 pr-10 py-2.5 text-base border-gray-300 dark:border-gray-500 outline-hidden focus:outline-hidden focus:ring-indigo-500 focus:border-indigo-500 rounded-md dark:text-gray-100"
/> />
</.form> </.form>
""" """

View File

@ -223,12 +223,12 @@ defmodule PlausibleWeb.Live.Components.Modal do
<div <div
x-show="modalOpen || modalPreopen" x-show="modalOpen || modalPreopen"
x-transition:enter="transition ease-out duration-300" x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="bg-opacity-0" x-transition:enter-start="bg-gray-500/0"
x-transition:enter-end="bg-opacity-75" x-transition:enter-end="bg-gray-500/75"
x-transition:leave="transition ease-in duration-200" x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="bg-opacity-75" x-transition:leave-start="bg-gray-500/75"
x-transition:leave-end="bg-opacity-0" x-transition:leave-end="bg-gray-500/0"
class="fixed inset-0 bg-gray-500 bg-opacity-75 z-[2050]" class="fixed inset-0 bg-gray-500/75 z-[2050]"
> >
</div> </div>
<div <div

View File

@ -112,7 +112,7 @@ defmodule PlausibleWeb.Live.Flash do
]} ]}
{@rest} {@rest}
> >
<div class="rounded-lg ring-1 ring-black ring-opacity-5 overflow-hidden"> <div class="rounded-lg ring-1/5 ring-black overflow-hidden">
<div class="p-4"> <div class="p-4">
<div class="flex items-start"> <div class="flex items-start">
{render_slot(@icon)} {render_slot(@icon)}
@ -124,7 +124,7 @@ defmodule PlausibleWeb.Live.Flash do
{render_slot(@message)} {render_slot(@message)}
</p> </p>
</div> </div>
<div class="ml-4 flex-shrink-0 flex"> <div class="ml-4 shrink-0 flex">
<.clear_flash_button on_close={@on_close} key={@key} /> <.clear_flash_button on_close={@on_close} key={@key} />
</div> </div>
</div> </div>
@ -136,7 +136,7 @@ defmodule PlausibleWeb.Live.Flash do
def icon_success(assigns) do def icon_success(assigns) do
~H""" ~H"""
<div class="flex-shrink-0"> <div class="shrink-0">
<svg <svg
class="h-6 w-6 text-green-400" class="h-6 w-6 text-green-400"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -178,7 +178,7 @@ defmodule PlausibleWeb.Live.Flash do
def clear_flash_button(assigns) do def clear_flash_button(assigns) do
~H""" ~H"""
<button <button
class="inline-flex text-gray-400 focus:outline-none focus:text-gray-500 dark:focus:text-gray-200 transition ease-in-out duration-150" class="inline-flex text-gray-400 focus:outline-hidden focus:text-gray-500 dark:focus:text-gray-200 transition ease-in-out duration-150"
phx-click={@on_close} phx-click={@on_close}
phx-value-key={@key} phx-value-key={@key}
> >

View File

@ -442,7 +442,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
def tabs(assigns) do def tabs(assigns) do
~H""" ~H"""
<div class="text-sm mt-6 font-medium dark:text-gray-100">Goal Trigger</div> <div class="text-sm mt-6 font-medium dark:text-gray-100">Goal Trigger</div>
<div class="my-2 text-sm w-full flex rounded border border-gray-300 dark:border-gray-500 overflow-hidden"> <div class="my-2 text-sm w-full flex rounded-sm border border-gray-300 dark:border-gray-500 overflow-hidden">
<.custom_events_tab selected?={@selected_tab == "custom_events"} myself={@myself} /> <.custom_events_tab selected?={@selected_tab == "custom_events"} myself={@myself} />
<.pageviews_tab selected?={@selected_tab == "pageviews"} myself={@myself} /> <.pageviews_tab selected?={@selected_tab == "pageviews"} myself={@myself} />
<.scroll_tab selected?={@selected_tab == "scroll"} myself={@myself} /> <.scroll_tab selected?={@selected_tab == "scroll"} myself={@myself} />

View File

@ -312,7 +312,7 @@ defmodule PlausibleWeb.Live.Installation do
id={"check-#{@variant}"} id={"check-#{@variant}"}
name={@variant} name={@variant}
checked={Map.get(@config, @variant, false)} checked={Map.get(@config, @variant, false)}
class="block h-5 w-5 rounded dark:bg-gray-700 border-gray-300 text-indigo-600 focus:ring-indigo-600 mr-2" class="block h-5 w-5 rounded-sm dark:bg-gray-700 border-gray-300 text-indigo-600 focus:ring-indigo-600 mr-2"
/> />
<label for={"check-#{@variant}"}> <label for={"check-#{@variant}"}>
{@label} {@label}

View File

@ -46,7 +46,7 @@ defmodule PlausibleWeb.Live.Plugins.API.TokenForm do
def render(assigns) do def render(assigns) do
~H""" ~H"""
<div <div
class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity z-50" class="fixed inset-0 bg-gray-500/75 transition-opacity z-50"
phx-window-keydown="close-tokens-modal" phx-window-keydown="close-tokens-modal"
phx-key="Escape" phx-key="Escape"
> >
@ -54,7 +54,7 @@ defmodule PlausibleWeb.Live.Plugins.API.TokenForm do
<div class="fixed inset-0 flex items-center justify-center mt-16 z-50 overflow-y-auto overflow-x-hidden"> <div class="fixed inset-0 flex items-center justify-center mt-16 z-50 overflow-y-auto overflow-x-hidden">
<div class="w-1/2 h-full"> <div class="w-1/2 h-full">
<div <div
class="max-w-md w-full mx-auto bg-white dark:bg-gray-800 shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8" class="max-w-md w-full mx-auto bg-white dark:bg-gray-800 shadow-md rounded-sm px-8 pt-6 pb-8 mb-4 mt-8"
phx-click-away="close-token-modal" phx-click-away="close-token-modal"
> >
<%= if @token_generated do %> <%= if @token_generated do %>

View File

@ -42,7 +42,7 @@ defmodule PlausibleWeb.Live.PropsSettings.Form do
def render(assigns) do def render(assigns) do
~H""" ~H"""
<div <div
class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity z-50" class="fixed inset-0 bg-gray-500/75 transition-opacity z-50"
phx-window-keydown="cancel-allow-prop" phx-window-keydown="cancel-allow-prop"
phx-key="Escape" phx-key="Escape"
> >
@ -52,7 +52,7 @@ defmodule PlausibleWeb.Live.PropsSettings.Form do
<.form <.form
:let={f} :let={f}
for={@form} for={@form}
class="max-w-md w-full mx-auto bg-white dark:bg-gray-800 shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8" class="max-w-md w-full mx-auto bg-white dark:bg-gray-800 shadow-md rounded-sm px-8 pt-6 pb-8 mb-4 mt-8"
phx-submit="allow-prop" phx-submit="allow-prop"
phx-click-away="cancel-allow-prop" phx-click-away="cancel-allow-prop"
> >

View File

@ -52,7 +52,7 @@ defmodule PlausibleWeb.Live.RegisterForm do
<div class="text-xl font-medium">Lightweight and privacy-friendly web analytics</div> <div class="text-xl font-medium">Lightweight and privacy-friendly web analytics</div>
</div> </div>
<div class="w-full max-w-md mx-auto bg-white dark:bg-gray-800 shadow-md rounded px-8 py-6 mb-4 mt-8"> <div class="w-full max-w-md mx-auto bg-white dark:bg-gray-800 shadow-md rounded-sm px-8 py-6 mb-4 mt-8">
<h2 class="text-xl font-black dark:text-gray-100">Invitation expired</h2> <h2 class="text-xl font-black dark:text-gray-100">Invitation expired</h2>
<p class="mt-4"> <p class="mt-4">
@ -133,7 +133,7 @@ defmodule PlausibleWeb.Live.RegisterForm do
field={f[:password]} field={f[:password]}
strength={@password_strength} strength={@password_strength}
phx-debounce={200} phx-debounce={200}
class="dark:bg-gray-900 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full border-gray-300 dark:border-gray-500 rounded-md dark:text-gray-300" class="dark:bg-gray-900 shadow-xs focus:ring-indigo-500 focus:border-indigo-500 block w-full border-gray-300 dark:border-gray-500 rounded-md dark:text-gray-300"
/> />
</div> </div>
</div> </div>
@ -151,7 +151,7 @@ defmodule PlausibleWeb.Live.RegisterForm do
autocomplete="new-password" autocomplete="new-password"
field={f[:password_confirmation]} field={f[:password_confirmation]}
phx-debounce={200} phx-debounce={200}
class="dark:bg-gray-900 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full border-gray-300 dark:border-gray-500 rounded-md dark:text-gray-300" class="dark:bg-gray-900 shadow-xs focus:ring-indigo-500 focus:border-indigo-500 block w-full border-gray-300 dark:border-gray-500 rounded-md dark:text-gray-300"
/> />
</div> </div>
</div> </div>
@ -191,7 +191,7 @@ defmodule PlausibleWeb.Live.RegisterForm do
{submit_text} {submit_text}
</.button> </.button>
<p class="text-center text-gray-600 dark:text-gray-500 mt-4"> <p class="text-center text-gray-600 dark:text-gray-500 mt-4">
Already have an account? Already have an account?
<.styled_link href="/login"> <.styled_link href="/login">
Log in Log in
@ -213,7 +213,7 @@ defmodule PlausibleWeb.Live.RegisterForm do
field={@field} field={@field}
placeholder="Jane Doe" placeholder="Jane Doe"
phx-debounce={200} phx-debounce={200}
class="dark:bg-gray-900 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full border-gray-300 dark:border-gray-500 rounded-md dark:text-gray-300" class="dark:bg-gray-900 shadow-xs focus:ring-indigo-500 focus:border-indigo-500 block w-full border-gray-300 dark:border-gray-500 rounded-md dark:text-gray-300"
/> />
</div> </div>
</div> </div>

View File

@ -33,7 +33,7 @@ defmodule PlausibleWeb.Live.ResetPasswordForm do
phx-change="validate" phx-change="validate"
phx-submit="set" phx-submit="set"
phx-trigger-action={@trigger_submit} phx-trigger-action={@trigger_submit}
class="bg-white dark:bg-gray-800 max-w-md w-full mx-auto shadow-md rounded px-8 py-6 mt-8" class="bg-white dark:bg-gray-800 max-w-md w-full mx-auto shadow-md rounded-sm px-8 py-6 mt-8"
> >
<input name="_csrf_token" type="hidden" value={Plug.CSRFProtection.get_csrf_token()} /> <input name="_csrf_token" type="hidden" value={Plug.CSRFProtection.get_csrf_token()} />
<h2 class="text-xl font-black dark:text-gray-100"> <h2 class="text-xl font-black dark:text-gray-100">
@ -51,7 +51,7 @@ defmodule PlausibleWeb.Live.ResetPasswordForm do
field={f[:password]} field={f[:password]}
strength={@password_strength} strength={@password_strength}
phx-debounce={200} phx-debounce={200}
class="transition bg-gray-100 dark:bg-gray-900 outline-none appearance-none border border-transparent rounded w-full p-2 text-gray-700 dark:text-gray-300 leading-normal appearance-none focus:outline-none focus:bg-white dark:focus:bg-gray-800 focus:border-gray-300 dark:focus:border-gray-500" class="transition bg-gray-100 dark:bg-gray-900 outline-hidden appearance-none border border-transparent rounded-xs w-full p-2 text-gray-700 dark:text-gray-300 leading-normal focus:outline-hidden focus:bg-white dark:focus:bg-gray-800 focus:border-gray-300 dark:focus:border-gray-500"
/> />
</div> </div>
<.button id="set" type="submit" class="mt-4 w-full"> <.button id="set" type="submit" class="mt-4 w-full">

View File

@ -62,7 +62,7 @@ defmodule PlausibleWeb.Live.Sites do
} /> } />
<div class="group mt-6 pb-5 border-b border-gray-200 dark:border-gray-500 flex items-center justify-between"> <div class="group mt-6 pb-5 border-b border-gray-200 dark:border-gray-500 flex items-center justify-between">
<h2 class="text-2xl font-bold leading-7 text-gray-900 dark:text-gray-100 sm:text-3xl sm:leading-9 sm:truncate flex-shrink-0"> <h2 class="text-2xl font-bold leading-7 text-gray-900 dark:text-gray-100 sm:text-3xl sm:leading-9 sm:truncate shrink-0">
{Teams.name(@current_team)} {Teams.name(@current_team)}
<.unstyled_link <.unstyled_link
:if={Teams.setup?(@current_team)} :if={Teams.setup?(@current_team)}
@ -141,7 +141,7 @@ defmodule PlausibleWeb.Live.Sites do
~H""" ~H"""
<div class="rounded-md bg-yellow-100 p-4"> <div class="rounded-md bg-yellow-100 p-4">
<div class="flex"> <div class="flex">
<div class="flex-shrink-0"> <div class="shrink-0">
<svg <svg
class="h-5 w-5 text-yellow-400" class="h-5 w-5 text-yellow-400"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -186,12 +186,12 @@ defmodule PlausibleWeb.Live.Sites do
data-domain={@site.domain} data-domain={@site.domain}
x-on:click={"invitationOpen = true; selectedInvitation = invitations['#{@invitation.invitation_id}']"} x-on:click={"invitationOpen = true; selectedInvitation = invitations['#{@invitation.invitation_id}']"}
> >
<div class="col-span-1 bg-white dark:bg-gray-800 rounded-md shadow p-4 group-hover:shadow-lg cursor-pointer transition duration-100"> <div class="col-span-1 bg-white dark:bg-gray-800 rounded-md shadow-sm p-4 group-hover:shadow-lg cursor-pointer transition duration-100">
<div class="w-full flex items-center justify-between space-x-4"> <div class="w-full flex items-center justify-between space-x-4">
<img <img
src={"/favicon/sources/#{@site.domain}"} src={"/favicon/sources/#{@site.domain}"}
onerror="this.onerror=null; this.src='/favicon/sources/placeholder';" onerror="this.onerror=null; this.src='/favicon/sources/placeholder';"
class="size-[1.15rem] flex-shrink-0" class="size-[1.15rem] shrink-0"
/> />
<div class="flex-1 truncate -mt-px"> <div class="flex-1 truncate -mt-px">
<h3 class="text-gray-900 font-medium text-lg truncate dark:text-gray-100"> <h3 class="text-gray-900 font-medium text-lg truncate dark:text-gray-100">
@ -199,7 +199,7 @@ defmodule PlausibleWeb.Live.Sites do
</h3> </h3>
</div> </div>
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-green-100 text-green-800"> <span class="inline-flex items-center px-2 py-0.5 rounded-sm text-xs font-medium bg-green-100 text-green-800">
Pending invitation Pending invitation
</span> </span>
</div> </div>
@ -232,7 +232,7 @@ defmodule PlausibleWeb.Live.Sites do
} }
> >
<.unstyled_link href={"/#{URI.encode_www_form(@site.domain)}"}> <.unstyled_link href={"/#{URI.encode_www_form(@site.domain)}"}>
<div class="col-span-1 bg-white dark:bg-gray-800 rounded-md shadow p-4 group-hover:shadow-lg cursor-pointer transition duration-100"> <div class="col-span-1 bg-white dark:bg-gray-800 rounded-md shadow-sm p-4 group-hover:shadow-lg cursor-pointer transition duration-100">
<div class="w-full flex items-center justify-between space-x-4"> <div class="w-full flex items-center justify-between space-x-4">
<.favicon domain={@site.domain} /> <.favicon domain={@site.domain} />
<div class="flex-1 -mt-px w-full"> <div class="flex-1 -mt-px w-full">
@ -425,7 +425,7 @@ defmodule PlausibleWeb.Live.Sites do
x-transition:leave="transition ease-in duration-200" x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100" x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0" x-transition:leave-end="opacity-0"
class="fixed inset-0 bg-gray-500 dark:bg-gray-800 bg-opacity-75 dark:bg-opacity-75 transition-opacity" class="fixed inset-0 bg-gray-500/75 dark:bg-gray-800/75 transition-opacity"
aria-hidden="true" aria-hidden="true"
x-on:click="invitationOpen = false" x-on:click="invitationOpen = false"
> >
@ -449,14 +449,14 @@ defmodule PlausibleWeb.Live.Sites do
<div class="hidden sm:block absolute top-0 right-0 pt-4 pr-4"> <div class="hidden sm:block absolute top-0 right-0 pt-4 pr-4">
<button <button
x-on:click="invitationOpen = false" x-on:click="invitationOpen = false"
class="bg-white dark:bg-gray-800 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" class="bg-white dark:bg-gray-800 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 focus:outline-hidden focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
> >
<span class="sr-only">Close</span> <span class="sr-only">Close</span>
<Heroicons.x_mark class="h-6 w-6" /> <Heroicons.x_mark class="h-6 w-6" />
</button> </button>
</div> </div>
<div class="sm:flex sm:items-start"> <div class="sm:flex sm:items-start">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-green-100 sm:mx-0 sm:h-10 sm:w-10"> <div class="mx-auto shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-green-100 sm:mx-0 sm:h-10 sm:w-10">
<Heroicons.user_group class="h-6 w-6" /> <Heroicons.user_group class="h-6 w-6" />
</div> </div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
@ -490,7 +490,7 @@ defmodule PlausibleWeb.Live.Sites do
<.notice <.notice
x-show="selectedInvitation && selectedInvitation.missing_features" x-show="selectedInvitation && selectedInvitation.missing_features"
title="Missing features" title="Missing features"
class="mt-4 shadow-sm dark:shadow-none" class="mt-4 shadow-xs dark:shadow-none"
> >
<p> <p>
The site uses <span x-text="selectedInvitation && selectedInvitation.missing_features"></span>, The site uses <span x-text="selectedInvitation && selectedInvitation.missing_features"></span>,
@ -507,7 +507,7 @@ defmodule PlausibleWeb.Live.Sites do
<.notice <.notice
x-show="selectedInvitation && selectedInvitation.exceeded_limits" x-show="selectedInvitation && selectedInvitation.exceeded_limits"
title="Unable to accept site ownership" title="Unable to accept site ownership"
class="mt-4 shadow-sm dark:shadow-none" class="mt-4 shadow-xs dark:shadow-none"
> >
<p> <p>
Owning this site would exceed your <span x-text="selectedInvitation && selectedInvitation.exceeded_limits"></span>. Please check your usage in Owning this site would exceed your <span x-text="selectedInvitation && selectedInvitation.exceeded_limits"></span>. Please check your usage in
@ -523,7 +523,7 @@ defmodule PlausibleWeb.Live.Sites do
<.notice <.notice
x-show="selectedInvitation && selectedInvitation.no_plan" x-show="selectedInvitation && selectedInvitation.no_plan"
title="No subscription" title="No subscription"
class="mt-4 shadow-sm dark:shadow-none" class="mt-4 shadow-xs dark:shadow-none"
> >
You are unable to accept the ownership of this site because your account does not have a subscription. To become the owner of this site, you should upgrade to a suitable plan. You are unable to accept the ownership of this site because your account does not have a subscription. To become the owner of this site, you should upgrade to a suitable plan.
</.notice> </.notice>
@ -575,7 +575,7 @@ defmodule PlausibleWeb.Live.Sites do
assigns = assign(assigns, :src, src) assigns = assign(assigns, :src, src)
~H""" ~H"""
<img src={@src} class="w-4 h-4 flex-shrink-0 mt-px" /> <img src={@src} class="w-4 h-4 shrink-0 mt-px" />
""" """
end end

View File

@ -65,7 +65,7 @@ defmodule PlausibleWeb.Live.TeamManagement do
</div> </div>
<.dropdown id="input-role-picker"> <.dropdown id="input-role-picker">
<:button class="role border rounded border-indigo-700 bg-transparent text-gray-800 dark:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-700 focus-visible:outline-gray-100 whitespace-nowrap truncate inline-flex items-center gap-x-2 font-medium rounded-md px-3 py-2 text-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 disabled:bg-gray-400 dark:disabled:text-white dark:disabled:text-gray-400 dark:disabled:bg-gray-700"> <:button class="role border rounded-sm border-indigo-700 bg-transparent text-gray-800 dark:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-700 focus-visible:outline-gray-100 whitespace-nowrap truncate inline-flex items-center gap-x-2 font-medium rounded-md px-3 py-2 text-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 disabled:bg-gray-400 dark:disabled:text-white dark:disabled:text-gray-400 dark:disabled:bg-gray-700">
{@input_role |> Atom.to_string() |> String.capitalize()} {@input_role |> Atom.to_string() |> String.capitalize()}
<Heroicons.chevron_down mini class="size-4 mt-0.5" /> <Heroicons.chevron_down mini class="size-4 mt-0.5" />
</:button> </:button>
@ -132,11 +132,11 @@ defmodule PlausibleWeb.Live.TeamManagement do
</div> </div>
<div :if={Layout.has_guests?(@layout)} class="flex items-center mt-4 mb-4" id="guests-hr"> <div :if={Layout.has_guests?(@layout)} class="flex items-center mt-4 mb-4" id="guests-hr">
<hr class="flex-grow border-t border-gray-200 dark:border-gray-600" /> <hr class="grow border-t border-gray-200 dark:border-gray-600" />
<span class="mx-4 text-gray-500 text-sm"> <span class="mx-4 text-gray-500 text-sm">
Guests Guests
</span> </span>
<hr class="flex-grow border-t border-gray-200 dark:border-gray-600" /> <hr class="grow border-t border-gray-200 dark:border-gray-600" />
</div> </div>
<div :if={Layout.has_guests?(@layout)} id="guest-list"> <div :if={Layout.has_guests?(@layout)} id="guest-list">

View File

@ -33,7 +33,7 @@
<.input type="hidden" field={f[:team_identifier]} /> <.input type="hidden" field={f[:team_identifier]} />
<.input <.input
field={f[:code]} field={f[:code]}
class="tracking-widest font-medium shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-36 px-8 border-gray-300 dark:border-gray-500 rounded-md dark:text-gray-200 dark:bg-gray-900 text-center" class="tracking-widest font-medium shadow-xs focus:ring-indigo-500 focus:border-indigo-500 block w-36 px-8 border-gray-300 dark:border-gray-500 rounded-md dark:text-gray-200 dark:bg-gray-900 text-center"
oninput="this.value=this.value.replace(/[^0-9]/g, ''); if (this.value.length >= 4) document.getElementById('submit').focus()" oninput="this.value=this.value.replace(/[^0-9]/g, ''); if (this.value.length >= 4) document.getElementById('submit').focus()"
onclick="this.select();" onclick="this.select();"
maxlength="4" maxlength="4"

View File

@ -1,4 +1,4 @@
<div class="bg-white dark:bg-gray-800 max-w-md w-full mx-auto shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8"> <div class="bg-white dark:bg-gray-800 max-w-md w-full mx-auto shadow-md rounded-sm px-8 pt-6 pb-8 mb-4 mt-8">
<h2 class="text-xl font-black dark:text-gray-100">Success!</h2> <h2 class="text-xl font-black dark:text-gray-100">Success!</h2>
<div class="my-4 leading-tight dark:text-gray-100"> <div class="my-4 leading-tight dark:text-gray-100">
We've sent an email containing password reset instructions to <b>{@email}</b> We've sent an email containing password reset instructions to <b>{@email}</b>

View File

@ -39,7 +39,7 @@
field={f[:remember_2fa]} field={f[:remember_2fa]}
value="true" value="true"
label={"Trust this device for #{@remember_2fa_days} days"} label={"Trust this device for #{@remember_2fa_days} days"}
class="block h-5 w-5 rounded dark:bg-gray-700 border-gray-300 text-indigo-600 focus:ring-indigo-600" class="block h-5 w-5 rounded-sm dark:bg-gray-700 border-gray-300 text-indigo-600 focus:ring-indigo-600"
/> />
</div> </div>

View File

@ -3,7 +3,7 @@
</div> </div>
<div class="w-full max-w-lg px-4 mx-auto mt-4"> <div class="w-full max-w-lg px-4 mx-auto mt-4">
<div class="flex-1 p-8 mt-8 bg-white rounded shadow-md dark:bg-gray-800"> <div class="flex-1 p-8 mt-8 bg-white rounded-sm shadow-md dark:bg-gray-800">
<div class="w-full pb-4 dark:text-gray-100"> <div class="w-full pb-4 dark:text-gray-100">
<span>Looking to adjust your plan?</span> <span>Looking to adjust your plan?</span>
</div> </div>

View File

@ -10,7 +10,7 @@
<div class="flex flex-col mt-4"> <div class="flex flex-col mt-4">
<div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8"> <div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
<div class="align-middle inline-block min-w-full shadow overflow-hidden sm:rounded-lg border-b border-gray-200 dark:border-t dark:border-l dark:border-r dark:shadow-none"> <div class="align-middle inline-block min-w-full shadow-sm overflow-hidden sm:rounded-lg border-b border-gray-200 dark:border-t dark:border-l dark:border-r dark:shadow-none">
<table class="min-w-full"> <table class="min-w-full">
<thead> <thead>
<tr> <tr>
@ -45,7 +45,7 @@
<div class="flex flex-col"> <div class="flex flex-col">
<div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8"> <div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
<div class="align-middle inline-block min-w-full shadow overflow-hidden sm:rounded-lg border-b border-gray-200 dark:border-t dark:border-l dark:border-r dark:shadow-none"> <div class="align-middle inline-block min-w-full shadow-sm overflow-hidden sm:rounded-lg border-b border-gray-200 dark:border-t dark:border-l dark:border-r dark:shadow-none">
<table class="min-w-full"> <table class="min-w-full">
<thead> <thead>
<tr> <tr>
@ -75,16 +75,16 @@
</div> </div>
<div class="flex items-center justify-between mt-10"> <div class="flex items-center justify-between mt-10">
<span class="flex rounded-md shadow-sm"> <span class="flex rounded-md shadow-xs">
<a <a
href={@back_link} href={@back_link}
type="button" type="button"
class="inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-500 text-sm leading-5 font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:text-gray-500 dark:hover:text-gray-200 focus:outline-none focus:border-blue-300 focus:ring active:text-gray-800 dark:active:text-gray-200 active:bg-gray-50 transition ease-in-out duration-150" class="inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-500 text-sm leading-5 font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:text-gray-500 dark:hover:text-gray-200 focus:outline-hidden focus:border-blue-300 focus:ring active:text-gray-800 dark:active:text-gray-200 active:bg-gray-50 transition ease-in-out duration-150"
> >
Back Back
</a> </a>
</span> </span>
<span class="flex space-betwee rounded-md shadow-sm"> <span class="flex space-betwee rounded-md shadow-xs">
<.button_link <.button_link
href={Routes.billing_path(@conn, :change_plan, @preview_info["plan_id"])} href={Routes.billing_path(@conn, :change_plan, @preview_info["plan_id"])}
method="post" method="post"

View File

@ -6,7 +6,7 @@
</h1> </h1>
</div> </div>
<div class="w-full max-w-lg px-4 mx-auto mt-4 text-gray-900 dark:text-gray-100"> <div class="w-full max-w-lg px-4 mx-auto mt-4 text-gray-900 dark:text-gray-100">
<div class="flex-1 p-8 mt-8 rounded bg-white shadow-md dark:bg-gray-800 dark:shadow-none"> <div class="flex-1 p-8 mt-8 rounded-sm bg-white shadow-md dark:bg-gray-800 dark:shadow-none">
<div class="w-full pb-4"> <div class="w-full pb-4">
<span> <span>
{if @subscription_resumable, {if @subscription_resumable,
@ -38,7 +38,7 @@
</ul> </ul>
<div class="w-max"> <div class="w-max">
<%= if @subscription_resumable do %> <%= if @subscription_resumable do %>
<span class="inline-flex w-full rounded-md shadow-sm"> <span class="inline-flex w-full rounded-md shadow-xs">
<.link <.link
id="preview-changes" id="preview-changes"
href={ href={
@ -48,7 +48,7 @@
@latest_enterprise_plan.paddle_plan_id @latest_enterprise_plan.paddle_plan_id
) )
} }
class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent leading-5 rounded-md hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:ring active:bg-indigo-700 transition ease-in-out duration-150" class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent leading-5 rounded-md hover:bg-indigo-500 focus:outline-hidden focus:border-indigo-700 focus:ring active:bg-indigo-700 transition ease-in-out duration-150"
> >
<svg fill="currentColor" viewBox="0 0 20 20" class="inline w-4 h-4 mr-2"> <svg fill="currentColor" viewBox="0 0 20 20" class="inline w-4 h-4 mr-2">
<path d="M10 12a2 2 0 100-4 2 2 0 000 4z"></path> <path d="M10 12a2 2 0 100-4 2 2 0 000 4z"></path>

View File

@ -1,4 +1,4 @@
<div class="w-full max-w-4xl bg-white dark:bg-gray-800 shadow-md rounded p-8 mb-4 mt-8 mx-auto"> <div class="w-full max-w-4xl bg-white dark:bg-gray-800 shadow-md rounded-sm p-8 mb-4 mt-8 mx-auto">
<section class="grid grid-cols-1 gap-y-3 divide-y"> <section class="grid grid-cols-1 gap-y-3 divide-y">
<%= for log <- @queries do %> <%= for log <- @queries do %>
<details class="group py-1"> <details class="group py-1">

View File

@ -1,10 +1,10 @@
<div class="w-full max-w-3xl mt-4 mx-auto flex"> <div class="w-full max-w-3xl mt-4 mx-auto flex">
<div class="max-w-lg w-full mx-auto bg-white dark:bg-gray-800 shadow-lg rounded px-8 pt-6 pb-8 mb-4 mt-8"> <div class="max-w-lg w-full mx-auto bg-white dark:bg-gray-800 shadow-lg rounded-sm px-8 pt-6 pb-8 mb-4 mt-8">
<h2 class="text-xl font-black dark:text-gray-100">Oops, sorry about that...</h2> <h2 class="text-xl font-black dark:text-gray-100">Oops, sorry about that...</h2>
<div class="rounded-md bg-yellow-50 dark:bg-transparent dark:border border-yellow-200 p-4 mt-4"> <div class="rounded-md bg-yellow-50 dark:bg-transparent dark:border border-yellow-200 p-4 mt-4">
<div class="flex"> <div class="flex">
<div class="flex-shrink-0"> <div class="shrink-0">
<svg <svg
class="h-5 w-5 text-yellow-400 dark:text-yellow-300" class="h-5 w-5 text-yellow-400 dark:text-yellow-300"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -57,7 +57,7 @@
name="user_feedback" name="user_feedback"
id="user_feedback" id="user_feedback"
rows="5" rows="5"
class="block w-full max-w-xl border-gray-300 dark:border-gray-700 resize-none shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-900 dark:text-gray-300" class="block w-full max-w-xl border-gray-300 dark:border-gray-700 resize-none shadow-xs focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-900 dark:text-gray-300"
placeholder="I clicked on 'X' and then hit 'Confirm'..." placeholder="I clicked on 'X' and then hit 'Confirm'..."
> >
</textarea> </textarea>

View File

@ -1,5 +1,5 @@
<div class="w-full max-w-3xl mt-4 mx-auto flex"> <div class="w-full max-w-3xl mt-4 mx-auto flex">
<div class="max-w-lg w-full mx-auto bg-white dark:bg-gray-800 shadow-lg rounded px-8 pt-6 pb-8 mb-4 mt-8"> <div class="max-w-lg w-full mx-auto bg-white dark:bg-gray-800 shadow-lg rounded-sm px-8 pt-6 pb-8 mb-4 mt-8">
<h2 class="text-xl font-black dark:text-gray-100">Thank you!</h2> <h2 class="text-xl font-black dark:text-gray-100">Thank you!</h2>
<div class="rounded-md dark:bg-transparent mt-4"> <div class="rounded-md dark:bg-transparent mt-4">

View File

@ -1,7 +1,7 @@
<.form <.form
:let={f} :let={f}
for={@conn} for={@conn}
class="max-w-md w-full mx-auto bg-white dark:bg-gray-800 shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8" class="max-w-md w-full mx-auto bg-white dark:bg-gray-800 shadow-md rounded-sm px-8 pt-6 pb-8 mb-4 mt-8"
onsubmit="confirmButton.disabled = true; return true;" onsubmit="confirmButton.disabled = true; return true;"
action={Routes.google_analytics_path(@conn, :import, @site.domain)} action={Routes.google_analytics_path(@conn, :import, @site.domain)}
> >

View File

@ -12,10 +12,10 @@
x-transition:leave-end="opacity-0" x-transition:leave-end="opacity-0"
class="max-w-sm w-full bg-white dark:bg-gray-800 shadow-lg rounded-lg pointer-events-auto" class="max-w-sm w-full bg-white dark:bg-gray-800 shadow-lg rounded-lg pointer-events-auto"
> >
<div class="rounded-lg ring-1 ring-black ring-opacity-5 overflow-hidden"> <div class="rounded-lg ring-1/5 ring-black overflow-hidden">
<div class="p-4"> <div class="p-4">
<div class="flex items-start"> <div class="flex items-start">
<div class="flex-shrink-0"> <div class="shrink-0">
<svg <svg
class="h-6 w-6 text-green-400" class="h-6 w-6 text-green-400"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -39,9 +39,9 @@
{Phoenix.Flash.get(@flash, :success)} {Phoenix.Flash.get(@flash, :success)}
</p> </p>
</div> </div>
<div class="ml-4 flex-shrink-0 flex"> <div class="ml-4 shrink-0 flex">
<button <button
class="inline-flex text-gray-400 focus:outline-none focus:text-gray-500 dark:focus:text-gray-200 transition ease-in-out duration-150" class="inline-flex text-gray-400 focus:outline-hidden focus:text-gray-500 dark:focus:text-gray-200 transition ease-in-out duration-150"
@click="show = false" @click="show = false"
> >
<!-- Heroicon name: x --> <!-- Heroicon name: x -->
@ -80,10 +80,10 @@
x-transition:leave-end="opacity-0" x-transition:leave-end="opacity-0"
class="max-w-sm w-full bg-white dark:bg-gray-800 shadow-lg rounded-lg pointer-events-auto" class="max-w-sm w-full bg-white dark:bg-gray-800 shadow-lg rounded-lg pointer-events-auto"
> >
<div class="rounded-lg ring-1 ring-black ring-opacity-5 overflow-hidden"> <div class="rounded-lg ring-1/5 ring-black overflow-hidden">
<div class="p-4"> <div class="p-4">
<div class="flex items-start"> <div class="flex items-start">
<div class="flex-shrink-0"> <div class="shrink-0">
<svg <svg
class="w-6 h-6 text-red-400" class="w-6 h-6 text-red-400"
fill="none" fill="none"
@ -108,9 +108,9 @@
{Phoenix.Flash.get(@flash, :error)} {Phoenix.Flash.get(@flash, :error)}
</p> </p>
</div> </div>
<div class="ml-4 flex-shrink-0 flex"> <div class="ml-4 shrink-0 flex">
<button <button
class="inline-flex text-gray-400 focus:outline-none focus:text-gray-500 dark:focus:text-gray-200 transition ease-in-out duration-150" class="inline-flex text-gray-400 focus:outline-hidden focus:text-gray-500 dark:focus:text-gray-200 transition ease-in-out duration-150"
@click="show = false" @click="show = false"
> >
<!-- Heroicon name: x --> <!-- Heroicon name: x -->

View File

@ -48,7 +48,7 @@
class="hidden mr-6 sm:block" class="hidden mr-6 sm:block"
> >
<.styled_link <.styled_link
class="text-sm text-yellow-900 dark:text-yellow-900 rounded px-3 py-2 rounded-md bg-yellow-100 dark:bg-yellow-100" class="text-sm text-yellow-900 dark:text-yellow-900 rounded-sm px-3 py-2 rounded-md bg-yellow-100 dark:bg-yellow-100"
href={Routes.settings_path(@conn, :subscription)} href={Routes.settings_path(@conn, :subscription)}
> >
{trial_notification(@conn.assigns[:current_team])} {trial_notification(@conn.assigns[:current_team])}
@ -149,7 +149,7 @@
<div class="inline-flex"> <div class="inline-flex">
<a <a
href="/login" href="/login"
class="font-medium text-gray-500 dark:text-gray-200 hover:text-gray-900 focus:outline-none focus:text-gray-900 transition duration-150 ease-in-out" class="font-medium text-gray-500 dark:text-gray-200 hover:text-gray-900 focus:outline-hidden focus:text-gray-900 transition duration-150 ease-in-out"
> >
Login Login
</a> </a>
@ -162,15 +162,15 @@
<div class="inline-flex"> <div class="inline-flex">
<a <a
href="/login" href="/login"
class="font-medium text-gray-500 dark:text-gray-200 hover:text-gray-900 focus:outline-none focus:text-gray-900 transition duration-150 ease-in-out" class="font-medium text-gray-500 dark:text-gray-200 hover:text-gray-900 focus:outline-hidden focus:text-gray-900 transition duration-150 ease-in-out"
> >
Login Login
</a> </a>
</div> </div>
<div class="inline-flex ml-6 rounded shadow"> <div class="inline-flex ml-6 rounded-sm shadow-sm">
<a <a
href="/register" href="/register"
class="inline-flex items-center justify-center px-5 py-2 text-base font-medium text-white bg-indigo-600 border border-transparent leading-6 rounded-md hover:bg-indigo-500 focus:outline-none focus:ring transition duration-150 ease-in-out" class="inline-flex items-center justify-center px-5 py-2 text-base font-medium text-white bg-indigo-600 border border-transparent leading-6 rounded-md hover:bg-indigo-500 focus:outline-hidden focus:ring transition duration-150 ease-in-out"
> >
Sign up Sign up
</a> </a>

View File

@ -33,7 +33,7 @@
team={@current_team} team={@current_team}
subscription={@subscription} subscription={@subscription}
/> />
<div class="w-full flex-1 h-32 px-2 py-4 text-center bg-gray-100 rounded dark:bg-gray-900"> <div class="w-full flex-1 h-32 px-2 py-4 text-center bg-gray-100 rounded-sm dark:bg-gray-900">
<h4 class="font-black dark:text-gray-100">Next bill amount</h4> <h4 class="font-black dark:text-gray-100">Next bill amount</h4>
<%= if Plausible.Billing.Subscription.Status.in?(@subscription, [Plausible.Billing.Subscription.Status.active(), Plausible.Billing.Subscription.Status.past_due()]) do %> <%= if Plausible.Billing.Subscription.Status.in?(@subscription, [Plausible.Billing.Subscription.Status.active(), Plausible.Billing.Subscription.Status.past_due()]) do %>
<div class="py-2 text-xl font-medium dark:text-gray-100"> <div class="py-2 text-xl font-medium dark:text-gray-100">
@ -46,7 +46,7 @@
<div class="py-2 text-xl font-medium dark:text-gray-100">---</div> <div class="py-2 text-xl font-medium dark:text-gray-100">---</div>
<% end %> <% end %>
</div> </div>
<div class="w-full flex-1 h-32 px-2 py-4 text-center bg-gray-100 rounded dark:bg-gray-900"> <div class="w-full flex-1 h-32 px-2 py-4 text-center bg-gray-100 rounded-sm dark:bg-gray-900">
<h4 class="font-black dark:text-gray-100">Next bill date</h4> <h4 class="font-black dark:text-gray-100">Next bill date</h4>
<%= if @subscription && @subscription.next_bill_date && Plausible.Billing.Subscription.Status.in?(@subscription, [Plausible.Billing.Subscription.Status.active(), Plausible.Billing.Subscription.Status.past_due()]) do %> <%= if @subscription && @subscription.next_bill_date && Plausible.Billing.Subscription.Status.in?(@subscription, [Plausible.Billing.Subscription.Status.active(), Plausible.Billing.Subscription.Status.past_due()]) do %>
@ -94,7 +94,7 @@
<%= if Application.get_env(:plausible, :environment) == "dev" do %> <%= if Application.get_env(:plausible, :environment) == "dev" do %>
<a <a
href={@subscription.update_url} href={@subscription.update_url}
class="ml-2 font-medium rounded-md px-3.5 py-2.5 text-sm shadow-sm border border-gray-300 dark:border-gray-500 text-yellow-600 dark:text-yellow-400 bg-white dark:bg-gray-900" class="ml-2 font-medium rounded-md px-3.5 py-2.5 text-sm shadow-xs border border-gray-300 dark:border-gray-500 text-yellow-600 dark:text-yellow-400 bg-white dark:bg-gray-900"
> >
[DEV ONLY] Change subscription status [DEV ONLY] Change subscription status
</a> </a>

View File

@ -33,7 +33,7 @@
<%= for membership <- @memberships do %> <%= for membership <- @memberships do %>
<li class="py-4" id={"membership-#{membership.user.id}"}> <li class="py-4" id={"membership-#{membership.user.id}"}>
<div class="flex items-center space-x-4"> <div class="flex items-center space-x-4">
<div class="flex-shrink-0"> <div class="shrink-0">
<img <img
src={Plausible.Auth.User.profile_img_url(membership.user)} src={Plausible.Auth.User.profile_img_url(membership.user)}
class="h-8 w-8 rounded-full" class="h-8 w-8 rounded-full"

View File

@ -144,7 +144,7 @@
rows="6" rows="6"
readonly="readonly" readonly="readonly"
onclick="this.select()" onclick="this.select()"
class="block w-full border-gray-300 dark:border-gray-700 resize-none text-sm shadow-sm focus:ring-indigo-500 focus:border-indigo-500 rounded-md dark:bg-gray-900 dark:text-gray-300" class="block w-full border-gray-300 dark:border-gray-700 resize-none text-sm shadow-xs focus:ring-indigo-500 focus:border-indigo-500 rounded-md dark:bg-gray-900 dark:text-gray-300"
></textarea> ></textarea>
<a <a
onclick="var textarea = document.getElementById('embed-code'); textarea.focus(); textarea.select(); document.execCommand('copy');" onclick="var textarea = document.getElementById('embed-code'); textarea.focus(); textarea.select(); document.execCommand('copy');"

View File

@ -1,5 +1,5 @@
<div class="w-full max-w-lg mx-auto mt-8"> <div class="w-full max-w-lg mx-auto mt-8">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg"> <div class="bg-white dark:bg-gray-800 shadow-sm sm:rounded-lg">
<div class="px-4 py-5 sm:px-8 sm:py-6"> <div class="px-4 py-5 sm:px-8 sm:py-6">
<div class="mx-auto flex items-center justify-center rounded-full bg-green-100 h-12 w-12"> <div class="mx-auto flex items-center justify-center rounded-full bg-green-100 h-12 w-12">
<svg <svg

View File

@ -3,7 +3,7 @@
<%= if Plausible.Teams.locked?(@site.team) do %> <%= if Plausible.Teams.locked?(@site.team) do %>
<div <div
class="w-full px-4 py-4 text-sm font-bold text-center text-yellow-800 bg-yellow-100 rounded transition" class="w-full px-4 py-4 text-sm font-bold text-center text-yellow-800 bg-yellow-100 rounded-sm transition"
style="top: 91px" style="top: 91px"
role="alert" role="alert"
> >
@ -59,19 +59,19 @@
Want these stats for your website? <br /> Want these stats for your website? <br />
<span class="text-indigo-600">Start your free trial today.</span> <span class="text-indigo-600">Start your free trial today.</span>
</h2> </h2>
<div class="flex mt-8 lg:flex-shrink-0 lg:mt-0"> <div class="flex mt-8 lg:shrink-0 lg:mt-0">
<div class="inline-flex shadow rounded-md"> <div class="inline-flex shadow-sm rounded-md">
<a <a
href="/register" href="/register"
class="inline-flex items-center justify-center px-5 py-3 text-base font-medium text-white bg-indigo-600 border border-transparent leading-6 rounded-md hover:bg-indigo-500 focus:outline-none focus:ring transition duration-150 ease-in-out" class="inline-flex items-center justify-center px-5 py-3 text-base font-medium text-white bg-indigo-600 border border-transparent leading-6 rounded-md hover:bg-indigo-500 focus:outline-hidden focus:ring transition duration-150 ease-in-out"
> >
Get started Get started
</a> </a>
</div> </div>
<div class="inline-flex ml-3 shadow rounded-md"> <div class="inline-flex ml-3 shadow-xs rounded-md">
<a <a
href="/" href="/"
class="inline-flex items-center justify-center px-5 py-3 text-base font-medium text-indigo-600 bg-white border border-transparent leading-6 rounded-md dark:text-gray-100 dark:bg-gray-800 hover:text-indigo-500 dark:hover:text-indigo-500 focus:outline-none focus:ring transition duration-150 ease-in-out" class="inline-flex items-center justify-center px-5 py-3 text-base font-medium text-indigo-600 bg-white border border-transparent leading-6 rounded-md dark:text-gray-100 dark:bg-gray-800 hover:text-indigo-500 dark:hover:text-indigo-500 focus:outline-hidden focus:ring transition duration-150 ease-in-out"
> >
Learn more Learn more
</a> </a>

View File

@ -138,7 +138,7 @@ defmodule Plausible.MixProject do
{:paginator, git: "https://github.com/duffelhq/paginator.git"}, {:paginator, git: "https://github.com/duffelhq/paginator.git"},
{:scrivener_ecto, "~> 2.0"}, {:scrivener_ecto, "~> 2.0"},
{:esbuild, "~> 0.7", runtime: Mix.env() in [:dev, :ce_dev]}, {:esbuild, "~> 0.7", runtime: Mix.env() in [:dev, :ce_dev]},
{:tailwind, "~> 0.2.0", runtime: Mix.env() in [:dev, :ce_dev]}, {:tailwind, "~> 0.4.0", runtime: Mix.env() in [:dev, :ce_dev]},
{:ex_json_logger, "~> 1.4.0"}, {:ex_json_logger, "~> 1.4.0"},
{:ecto_network, "~> 1.5.0"}, {:ecto_network, "~> 1.5.0"},
{:ex_aws, "~> 2.5"}, {:ex_aws, "~> 2.5"},

View File

@ -8,7 +8,7 @@
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.1.0", "0b110a9a6c619b19a7f73fa3004aa11d6e719a67e672d1633dc36b6b2290a0f7", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2ad2acb5a8bc049e8d5aa267802631912bb80d5f4110a178ae7999e69dca1bf7"}, "bcrypt_elixir": {:hex, :bcrypt_elixir, "3.1.0", "0b110a9a6c619b19a7f73fa3004aa11d6e719a67e672d1633dc36b6b2290a0f7", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2ad2acb5a8bc049e8d5aa267802631912bb80d5f4110a178ae7999e69dca1bf7"},
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
"bypass": {:hex, :bypass, "2.1.0", "909782781bf8e20ee86a9cabde36b259d44af8b9f38756173e8f5e2e1fabb9b1", [:mix], [{:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "d9b5df8fa5b7a6efa08384e9bbecfe4ce61c77d28a4282f79e02f1ef78d96b80"}, "bypass": {:hex, :bypass, "2.1.0", "909782781bf8e20ee86a9cabde36b259d44af8b9f38756173e8f5e2e1fabb9b1", [:mix], [{:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "d9b5df8fa5b7a6efa08384e9bbecfe4ce61c77d28a4282f79e02f1ef78d96b80"},
"castore": {:hex, :castore, "1.0.14", "4582dd7d630b48cf5e1ca8d3d42494db51e406b7ba704e81fbd401866366896a", [:mix], [], "hexpm", "7bc1b65249d31701393edaaac18ec8398d8974d52c647b7904d01b964137b9f4"}, "castore": {:hex, :castore, "1.0.15", "8aa930c890fe18b6fe0a0cff27b27d0d4d231867897bd23ea772dee561f032a3", [:mix], [], "hexpm", "96ce4c69d7d5d7a0761420ef743e2f4096253931a3ba69e5ff8ef1844fe446d3"},
"certifi": {:hex, :certifi, "2.14.0", "ed3bef654e69cde5e6c022df8070a579a79e8ba2368a00acf3d75b82d9aceeed", [:rebar3], [], "hexpm", "ea59d87ef89da429b8e905264fdec3419f84f2215bb3d81e07a18aac919026c3"}, "certifi": {:hex, :certifi, "2.14.0", "ed3bef654e69cde5e6c022df8070a579a79e8ba2368a00acf3d75b82d9aceeed", [:rebar3], [], "hexpm", "ea59d87ef89da429b8e905264fdec3419f84f2215bb3d81e07a18aac919026c3"},
"ch": {:hex, :ch, "0.4.1", "716fc326a0d29212a35c15e5350355550ff1290a244e6f37bf3eac4318aeeb76", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.13.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "e6a4cf90d22030afde77e1a2895ebba2888032ccc5f1bec947b26b90a9152ffc"}, "ch": {:hex, :ch, "0.4.1", "716fc326a0d29212a35c15e5350355550ff1290a244e6f37bf3eac4318aeeb76", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.13.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "e6a4cf90d22030afde77e1a2895ebba2888032ccc5f1bec947b26b90a9152ffc"},
"chatterbox": {:hex, :ts_chatterbox, "0.15.1", "5cac4d15dd7ad61fc3c4415ce4826fc563d4643dee897a558ec4ea0b1c835c9c", [:rebar3], [{:hpack, "~> 0.3.0", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "4f75b91451338bc0da5f52f3480fa6ef6e3a2aeecfc33686d6b3d0a0948f31aa"}, "chatterbox": {:hex, :ts_chatterbox, "0.15.1", "5cac4d15dd7ad61fc3c4415ce4826fc563d4643dee897a558ec4ea0b1c835c9c", [:rebar3], [{:hpack, "~> 0.3.0", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "4f75b91451338bc0da5f52f3480fa6ef6e3a2aeecfc33686d6b3d0a0948f31aa"},
@ -150,7 +150,7 @@
"site_encrypt": {:git, "https://github.com/sasa1977/site_encrypt.git", "8d47801c51eeea11ac385cb73eef4ed9a6565367", []}, "site_encrypt": {:git, "https://github.com/sasa1977/site_encrypt.git", "8d47801c51eeea11ac385cb73eef4ed9a6565367", []},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
"sweet_xml": {:hex, :sweet_xml, "0.7.4", "a8b7e1ce7ecd775c7e8a65d501bc2cd933bff3a9c41ab763f5105688ef485d08", [:mix], [], "hexpm", "e7c4b0bdbf460c928234951def54fe87edf1a170f6896675443279e2dbeba167"}, "sweet_xml": {:hex, :sweet_xml, "0.7.4", "a8b7e1ce7ecd775c7e8a65d501bc2cd933bff3a9c41ab763f5105688ef485d08", [:mix], [], "hexpm", "e7c4b0bdbf460c928234951def54fe87edf1a170f6896675443279e2dbeba167"},
"tailwind": {:hex, :tailwind, "0.2.2", "9e27288b568ede1d88517e8c61259bc214a12d7eed271e102db4c93fcca9b2cd", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "ccfb5025179ea307f7f899d1bb3905cd0ac9f687ed77feebc8f67bdca78565c4"}, "tailwind": {:hex, :tailwind, "0.4.0", "4b2606713080437e3d94a0fa26527e7425737abc001f172b484b42f43e3274c0", [:mix], [], "hexpm", "530bd35699333f8ea0e9038d7146c2f0932dfec2e3636bd4a8016380c4bc382e"},
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
"telemetry_metrics": {:hex, :telemetry_metrics, "1.1.0", "5bd5f3b5637e0abea0426b947e3ce5dd304f8b3bc6617039e2b5a008adc02f8f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7b79e8ddfde70adb6db8a6623d1778ec66401f366e9a8f5dd0955c56bc8ce67"}, "telemetry_metrics": {:hex, :telemetry_metrics, "1.1.0", "5bd5f3b5637e0abea0426b947e3ce5dd304f8b3bc6617039e2b5a008adc02f8f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7b79e8ddfde70adb6db8a6623d1778ec66401f366e9a8f5dd0955c56bc8ce67"},
"telemetry_metrics_prometheus_core": {:hex, :telemetry_metrics_prometheus_core, "1.2.1", "c9755987d7b959b557084e6990990cb96a50d6482c683fb9622a63837f3cd3d8", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "5e2c599da4983c4f88a33e9571f1458bf98b0cf6ba930f1dc3a6e8cf45d5afb6"}, "telemetry_metrics_prometheus_core": {:hex, :telemetry_metrics_prometheus_core, "1.2.1", "c9755987d7b959b557084e6990990cb96a50d6482c683fb9622a63837f3cd3d8", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "5e2c599da4983c4f88a33e9571f1458bf98b0cf6ba930f1dc3a6e8cf45d5afb6"},