init go project
This commit is contained in:
commit
5dde43e409
85 changed files with 16720 additions and 0 deletions
332
internal/ui/components/dialog/dialog.templ
Normal file
332
internal/ui/components/dialog/dialog.templ
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
// templui component dialog - version: v0.101.0 installed by templui v0.101.0
|
||||
// 📚 Documentation: https://templui.io/docs/components/dialog
|
||||
package dialog
|
||||
|
||||
import (
|
||||
"context"
|
||||
"git.juancwu.dev/juancwu/budgething/internal/ui/components/icon"
|
||||
"git.juancwu.dev/juancwu/budgething/internal/utils"
|
||||
)
|
||||
|
||||
type contextKey string
|
||||
|
||||
const (
|
||||
instanceKey contextKey = "dialogInstance"
|
||||
openKey contextKey = "dialogOpen"
|
||||
)
|
||||
|
||||
type Props struct {
|
||||
ID string
|
||||
Class string
|
||||
Attributes templ.Attributes
|
||||
DisableClickAway bool
|
||||
DisableESC bool
|
||||
Open bool
|
||||
}
|
||||
|
||||
type TriggerProps struct {
|
||||
ID string
|
||||
Class string
|
||||
Attributes templ.Attributes
|
||||
For string // Reference to a specific dialog ID (for external triggers)
|
||||
}
|
||||
|
||||
type ContentProps struct {
|
||||
ID string
|
||||
Class string
|
||||
Attributes templ.Attributes
|
||||
HideCloseButton bool
|
||||
Open bool // Initial open state for standalone usage (when no context)
|
||||
DisableAutoFocus bool
|
||||
}
|
||||
|
||||
type CloseProps struct {
|
||||
ID string
|
||||
Class string
|
||||
Attributes templ.Attributes
|
||||
For string // ID of the dialog to close (optional, defaults to closest dialog)
|
||||
}
|
||||
|
||||
type HeaderProps struct {
|
||||
ID string
|
||||
Class string
|
||||
Attributes templ.Attributes
|
||||
}
|
||||
|
||||
type FooterProps struct {
|
||||
ID string
|
||||
Class string
|
||||
Attributes templ.Attributes
|
||||
}
|
||||
|
||||
type TitleProps struct {
|
||||
ID string
|
||||
Class string
|
||||
Attributes templ.Attributes
|
||||
}
|
||||
|
||||
type DescriptionProps struct {
|
||||
ID string
|
||||
Class string
|
||||
Attributes templ.Attributes
|
||||
}
|
||||
|
||||
templ Dialog(props ...Props) {
|
||||
{{ var p Props }}
|
||||
if len(props) > 0 {
|
||||
{{ p = props[0] }}
|
||||
}
|
||||
{{ instanceID := p.ID }}
|
||||
if instanceID == "" {
|
||||
{{ instanceID = utils.RandomID() }}
|
||||
}
|
||||
{{ ctx = context.WithValue(ctx, instanceKey, instanceID) }}
|
||||
{{ ctx = context.WithValue(ctx, openKey, p.Open) }}
|
||||
<div
|
||||
if p.ID != "" {
|
||||
id={ p.ID }
|
||||
}
|
||||
data-tui-dialog
|
||||
data-dialog-instance={ instanceID }
|
||||
if p.DisableClickAway {
|
||||
data-tui-dialog-disable-click-away="true"
|
||||
}
|
||||
if p.DisableESC {
|
||||
data-tui-dialog-disable-esc="true"
|
||||
}
|
||||
class={ utils.TwMerge("", p.Class) }
|
||||
{ p.Attributes... }
|
||||
>
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
||||
|
||||
templ Trigger(props ...TriggerProps) {
|
||||
{{ var p TriggerProps }}
|
||||
if len(props) > 0 {
|
||||
{{ p = props[0] }}
|
||||
}
|
||||
{{ instanceID := "" }}
|
||||
// Explicit For prop takes priority over inherited context
|
||||
if p.For != "" {
|
||||
{{ instanceID = p.For }}
|
||||
} else if val := ctx.Value(instanceKey); val != nil {
|
||||
{{ instanceID = val.(string) }}
|
||||
}
|
||||
<span
|
||||
if p.ID != "" {
|
||||
id={ p.ID }
|
||||
}
|
||||
data-tui-dialog-trigger={ instanceID }
|
||||
data-dialog-instance={ instanceID }
|
||||
data-tui-dialog-trigger-open="false"
|
||||
class={ utils.TwMerge("contents", p.Class) }
|
||||
{ p.Attributes... }
|
||||
>
|
||||
{ children... }
|
||||
</span>
|
||||
}
|
||||
|
||||
templ Content(props ...ContentProps) {
|
||||
{{ var p ContentProps }}
|
||||
if len(props) > 0 {
|
||||
{{ p = props[0] }}
|
||||
}
|
||||
// Start with prop values as defaults
|
||||
{{ instanceID := p.ID }}
|
||||
{{ open := p.Open }}
|
||||
// Override with context values if available
|
||||
if val := ctx.Value(instanceKey); val != nil {
|
||||
{{ instanceID = val.(string) }}
|
||||
}
|
||||
if val := ctx.Value(openKey); val != nil {
|
||||
{{ open = val.(bool) }}
|
||||
}
|
||||
// Apply defaults if still empty
|
||||
if instanceID == "" {
|
||||
{{ instanceID = utils.RandomID() }}
|
||||
}
|
||||
<!-- Overlay -->
|
||||
<div
|
||||
class={ utils.TwMerge(
|
||||
"fixed inset-0 z-50 bg-black/50",
|
||||
"transition-opacity duration-300",
|
||||
"data-[tui-dialog-open=false]:opacity-0",
|
||||
"data-[tui-dialog-open=true]:opacity-100",
|
||||
"data-[tui-dialog-open=false]:pointer-events-none",
|
||||
"data-[tui-dialog-open=true]:pointer-events-auto",
|
||||
"data-[tui-dialog-hidden=true]:!hidden",
|
||||
) }
|
||||
data-tui-dialog-backdrop
|
||||
data-dialog-instance={ instanceID }
|
||||
if open {
|
||||
data-tui-dialog-open="true"
|
||||
} else {
|
||||
data-tui-dialog-open="false"
|
||||
data-tui-dialog-hidden="true"
|
||||
}
|
||||
></div>
|
||||
<!-- Content -->
|
||||
<div
|
||||
class={
|
||||
utils.TwMerge(
|
||||
// Base positioning
|
||||
"fixed z-50 left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%]",
|
||||
// Style
|
||||
"bg-background rounded-lg border shadow-lg",
|
||||
// Layout
|
||||
"grid gap-4 p-6",
|
||||
// Size
|
||||
"w-full max-w-[calc(100%-2rem)] sm:max-w-lg",
|
||||
// Transitions
|
||||
"transition-all duration-200",
|
||||
// Scale animation
|
||||
"data-[tui-dialog-open=false]:scale-95",
|
||||
"data-[tui-dialog-open=true]:scale-100",
|
||||
// Opacity
|
||||
"data-[tui-dialog-open=false]:opacity-0",
|
||||
"data-[tui-dialog-open=true]:opacity-100",
|
||||
// Pointer events
|
||||
"data-[tui-dialog-open=false]:pointer-events-none",
|
||||
"data-[tui-dialog-open=true]:pointer-events-auto",
|
||||
// Hidden state
|
||||
"data-[tui-dialog-hidden=true]:!hidden",
|
||||
p.Class,
|
||||
),
|
||||
}
|
||||
data-tui-dialog-content
|
||||
data-dialog-instance={ instanceID }
|
||||
if p.DisableAutoFocus {
|
||||
data-tui-dialog-disable-autofocus="true"
|
||||
}
|
||||
if open {
|
||||
data-tui-dialog-open="true"
|
||||
} else {
|
||||
data-tui-dialog-open="false"
|
||||
data-tui-dialog-hidden="true"
|
||||
}
|
||||
{ p.Attributes... }
|
||||
>
|
||||
{ children... }
|
||||
if !p.HideCloseButton {
|
||||
<button
|
||||
class={ utils.TwMerge(
|
||||
// Positioning
|
||||
"absolute top-4 right-4",
|
||||
// Style
|
||||
"rounded-xs opacity-70",
|
||||
// Interactions
|
||||
"transition-opacity hover:opacity-100",
|
||||
// Focus states
|
||||
"focus:outline-none focus:ring-2",
|
||||
"focus:ring-ring focus:ring-offset-2",
|
||||
"ring-offset-background",
|
||||
// Hover/Data states
|
||||
"data-[tui-dialog-open=true]:bg-accent",
|
||||
"data-[tui-dialog-open=true]:text-muted-foreground",
|
||||
// Disabled state
|
||||
"disabled:pointer-events-none",
|
||||
// Icon styles
|
||||
"[&_svg]:pointer-events-none",
|
||||
"[&_svg]:shrink-0",
|
||||
"[&_svg:not([class*='size-'])]:size-4",
|
||||
) }
|
||||
data-tui-dialog-close={ instanceID }
|
||||
aria-label="Close"
|
||||
type="button"
|
||||
>
|
||||
@icon.X()
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
templ Close(props ...CloseProps) {
|
||||
{{ var p CloseProps }}
|
||||
if len(props) > 0 {
|
||||
{{ p = props[0] }}
|
||||
}
|
||||
<span
|
||||
if p.ID != "" {
|
||||
id={ p.ID }
|
||||
}
|
||||
if p.For != "" {
|
||||
data-tui-dialog-close={ p.For }
|
||||
} else {
|
||||
data-tui-dialog-close
|
||||
}
|
||||
class={ utils.TwMerge("contents cursor-pointer", p.Class) }
|
||||
{ p.Attributes... }
|
||||
>
|
||||
{ children... }
|
||||
</span>
|
||||
}
|
||||
|
||||
templ Header(props ...HeaderProps) {
|
||||
{{ var p HeaderProps }}
|
||||
if len(props) > 0 {
|
||||
{{ p = props[0] }}
|
||||
}
|
||||
<div
|
||||
if p.ID != "" {
|
||||
id={ p.ID }
|
||||
}
|
||||
class={ utils.TwMerge("flex flex-col gap-2 text-center sm:text-left", p.Class) }
|
||||
{ p.Attributes... }
|
||||
>
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
||||
|
||||
templ Footer(props ...FooterProps) {
|
||||
{{ var p FooterProps }}
|
||||
if len(props) > 0 {
|
||||
{{ p = props[0] }}
|
||||
}
|
||||
<div
|
||||
if p.ID != "" {
|
||||
id={ p.ID }
|
||||
}
|
||||
class={ utils.TwMerge("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", p.Class) }
|
||||
{ p.Attributes... }
|
||||
>
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
||||
|
||||
templ Title(props ...TitleProps) {
|
||||
{{ var p TitleProps }}
|
||||
if len(props) > 0 {
|
||||
{{ p = props[0] }}
|
||||
}
|
||||
<h2
|
||||
if p.ID != "" {
|
||||
id={ p.ID }
|
||||
}
|
||||
class={ utils.TwMerge("text-lg leading-none font-semibold", p.Class) }
|
||||
{ p.Attributes... }
|
||||
>
|
||||
{ children... }
|
||||
</h2>
|
||||
}
|
||||
|
||||
templ Description(props ...DescriptionProps) {
|
||||
{{ var p DescriptionProps }}
|
||||
if len(props) > 0 {
|
||||
{{ p = props[0] }}
|
||||
}
|
||||
<p
|
||||
if p.ID != "" {
|
||||
id={ p.ID }
|
||||
}
|
||||
class={ utils.TwMerge("text-muted-foreground text-sm", p.Class) }
|
||||
{ p.Attributes... }
|
||||
>
|
||||
{ children... }
|
||||
</p>
|
||||
}
|
||||
|
||||
templ Script() {
|
||||
<script defer nonce={ templ.GetNonce(ctx) } src={ "/assets/js/dialog.min.js?v=" + utils.ScriptVersion }></script>
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue