diff options
Diffstat (limited to 'vendor/github.com/a-h/templ/once.go')
-rw-r--r-- | vendor/github.com/a-h/templ/once.go | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/vendor/github.com/a-h/templ/once.go b/vendor/github.com/a-h/templ/once.go new file mode 100644 index 0000000..7860ab8 --- /dev/null +++ b/vendor/github.com/a-h/templ/once.go @@ -0,0 +1,64 @@ +package templ + +import ( + "context" + "io" + "sync/atomic" +) + +// onceHandleIndex is used to identify unique once handles in a program run. +var onceHandleIndex int64 + +type OnceOpt func(*OnceHandle) + +// WithOnceComponent sets the component to be rendered once per context. +// This can be used instead of setting the children of the `Once` method, +// for example, if creating a code component outside of a templ HTML template. +func WithComponent(c Component) OnceOpt { + return func(o *OnceHandle) { + o.c = c + } +} + +// NewOnceHandle creates a OnceHandle used to ensure that the children of its +// `Once` method are only rendered once per context. +func NewOnceHandle(opts ...OnceOpt) *OnceHandle { + oh := &OnceHandle{ + id: atomic.AddInt64(&onceHandleIndex, 1), + } + for _, opt := range opts { + opt(oh) + } + return oh +} + +// OnceHandle is used to ensure that the children of its `Once` method are are only +// rendered once per context. +type OnceHandle struct { + // id is used to identify which instance of the OnceHandle is being used. + // The OnceHandle can't be an empty struct, because: + // + // | Two distinct zero-size variables may + // | have the same address in memory + // + // https://go.dev/ref/spec#Size_and_alignment_guarantees + id int64 + // c is the component to be rendered once per context. + // if c is nil, the children of the `Once` method are rendered. + c Component +} + +// Once returns a component that renders its children once per context. +func (o *OnceHandle) Once() Component { + return ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { + _, v := getContext(ctx) + if v.getHasBeenRendered(o) { + return nil + } + v.setHasBeenRendered(o) + if o.c != nil { + return o.c.Render(ctx, w) + } + return GetChildren(ctx).Render(ctx, w) + }) +} |